Compare commits
243 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 921944e64e | |||
| 9e00217cec | |||
| 04ad890f16 | |||
| a89558d5a7 | |||
| 5b8bdaca4b | |||
| d8b08b46fc | |||
| b33d2ace99 | |||
| 5ddb8b020b | |||
| 3831f4e0c0 | |||
| d8ff8876b4 | |||
| 036b9d1a94 | |||
| 8401d9eada | |||
| be28bf0dc8 | |||
| 0857a02c77 | |||
| e50d13b992 | |||
| 41f1593443 | |||
| 46652862d3 | |||
| 5bd8a5de42 | |||
| 646a62afdb | |||
| 169feb563f | |||
| fb99a3783f | |||
| a3d77ee98a | |||
|
|
e6fbb4f146 | ||
|
|
e4dc805422 | ||
|
|
87ee0ed66b | ||
|
|
adeea461fd | ||
|
|
1f7bafbfc3 | ||
|
|
b8420ba31c | ||
|
|
a5676eeb5a | ||
|
|
9a33b92392 | ||
|
|
97f993db7b | ||
|
|
6f0ab1890d | ||
|
|
c88f7796f4 | ||
|
|
0b5b47ae66 | ||
|
|
b6117a501f | ||
|
|
a34df84dfa | ||
|
|
6677e5c87d | ||
|
|
91fc3bbb03 | ||
|
|
460b03c668 | ||
|
|
8a2e5f5835 | ||
|
|
72fd974da1 | ||
|
|
e6166de04b | ||
|
|
f0213eadb1 | ||
|
|
ae23674f21 | ||
|
|
68e45e58a6 | ||
|
|
f1585a3b8c | ||
|
|
d1c1eb5db2 | ||
|
|
21cdfbbe1a | ||
|
|
7033f9f622 | ||
|
|
5106ed228e | ||
|
|
ab40037064 | ||
|
|
ed4f9cbaa7 | ||
|
|
c7357c0539 | ||
|
|
01c947f434 | ||
|
|
dc21eb52d0 | ||
|
|
c4ab20f9b5 | ||
|
|
b41a47587b | ||
|
|
11dba2b42c | ||
|
|
f1f085abcf | ||
|
|
18841b2a45 | ||
|
|
64d9f8173a | ||
|
|
78e2d9642f | ||
|
|
4a40b00695 | ||
|
|
0f7389dca8 | ||
|
|
640d027502 | ||
|
|
2bc6c86a8d | ||
|
|
67ccd1d684 | ||
|
|
81bc3c77c8 | ||
|
|
e0083f7085 | ||
|
|
5da140df1e | ||
|
|
1b0e072237 | ||
|
|
8178bd298b | ||
|
|
845dd5c98b | ||
|
|
45287711a4 | ||
|
|
b1831c137a | ||
|
|
1cdac65c00 | ||
|
|
c38bbba793 | ||
|
|
da1f011ab4 | ||
|
|
64f0cc36cc | ||
|
|
9034790c06 | ||
|
|
91d7218a47 | ||
|
|
97ced90466 | ||
|
|
fa3e73d52f | ||
|
|
602854d087 | ||
|
|
97ca9ae754 | ||
|
|
6a04e1d1fa | ||
|
|
da4be2993e | ||
|
|
abdb7f40f5 | ||
|
|
0187698826 | ||
| 05ae063b90 | |||
|
|
c5b1ff0b94 | ||
|
|
955dd1355a | ||
|
|
1615580de6 | ||
|
|
5526aa2f54 | ||
|
|
4ce2565b90 | ||
|
|
909d3618b3 | ||
|
|
1fa964d348 | ||
|
|
159b3340eb | ||
|
|
5fb3191124 | ||
|
|
cc6853f541 | ||
|
|
5d77207b66 | ||
|
|
a940db51c2 | ||
|
|
d47e31eaed | ||
|
|
92f9d5db8e | ||
|
|
af97b72b12 | ||
|
|
3f7a4c2063 | ||
|
|
111ec1154d | ||
|
|
db0929bd08 | ||
|
|
2ddede4d3f | ||
|
|
0e227e1e07 | ||
|
|
1d2ac0fd5c | ||
|
|
05e9d9e0a2 | ||
|
|
fcb5028aa2 | ||
|
|
c57e4eb2a4 | ||
|
|
feba2f4520 | ||
|
|
16e3a25f76 | ||
|
|
be1f9763e1 | ||
|
|
605df45b2f | ||
|
|
984133f61d | ||
|
|
6e40b8d9ed | ||
|
|
607b002985 | ||
|
|
0fae084ccb | ||
|
|
f00de1bd25 | ||
|
|
96b4ec8259 | ||
|
|
2b664c446b | ||
|
|
486c40048b | ||
|
|
84ad0484f9 | ||
|
|
b9549eb58e | ||
|
|
b06b19e2a8 | ||
|
|
4c2a5ab12a | ||
|
|
8b16bbdaed | ||
|
|
7e712dece4 | ||
|
|
52424dd067 | ||
|
|
fdf8c50413 | ||
|
|
1247f8172d | ||
|
|
9026eb76c5 | ||
|
|
c9441b2591 | ||
|
|
b4fc332f0a | ||
|
|
9544635e30 | ||
|
|
e95cbff3d5 | ||
|
|
05006284c6 | ||
|
|
c90fbdc3d1 | ||
|
|
2137000d05 | ||
|
|
b02ad32d5a | ||
|
|
7a7e08d4eb | ||
|
|
22a2aa2ad6 | ||
|
|
8c06e7aff7 | ||
|
|
b9af5dfaf3 | ||
|
|
3048b43b9a | ||
|
|
a26f607a8b | ||
|
|
1815f61280 | ||
|
|
eaf73c280b | ||
|
|
24a79963ba | ||
|
|
1cc6c64c04 | ||
|
|
17b39efee0 | ||
|
|
1c2d966763 | ||
|
|
72d45a0987 | ||
|
|
9fc4c7c6e1 | ||
|
|
4b340b4d4c | ||
|
|
f40a1c986d | ||
|
|
793523b0a7 | ||
|
|
eae7cdc204 | ||
|
|
e0e591db3e | ||
|
|
b8ca52e7f2 | ||
|
|
b912ccbf9c | ||
|
|
1411ff2c3b | ||
|
|
bc9d8867f3 | ||
|
|
ade852163b | ||
|
|
1caa75a7d2 | ||
|
|
56054c2634 | ||
|
|
36f724c66c | ||
|
|
d0b7c086ca | ||
|
|
54b99aca29 | ||
|
|
099e50b91e | ||
|
|
e655ee39ce | ||
|
|
7c44f15428 | ||
|
|
df5d0960dd | ||
|
|
492c348897 | ||
|
|
189b9ff6f6 | ||
|
|
a77cb0e258 | ||
|
|
64ca9f78da | ||
|
|
d91c9d5687 | ||
|
|
1164845b3c | ||
|
|
e40ce4d5ad | ||
|
|
fcdbc60f16 | ||
|
|
3740d7ee2d | ||
|
|
28604f08a3 | ||
|
|
b646bc92cc | ||
|
|
9587e2f494 | ||
|
|
2115a26d9d | ||
|
|
b2823e79be | ||
|
|
4a123f5df6 | ||
|
|
bd8f812e01 | ||
|
|
6923a3ddb0 | ||
|
|
20c4ff5559 | ||
|
|
770ce1cc23 | ||
|
|
1ebd6de6a1 | ||
|
|
047fb72394 | ||
|
|
b35fa3cf50 | ||
|
|
47034d7901 | ||
|
|
d56a1d34ff | ||
|
|
63068ed9c7 | ||
|
|
2eb8e0b7cb | ||
|
|
0347d25fc9 | ||
|
|
9a365000ad | ||
|
|
be458afcc4 | ||
|
|
197f469bd8 | ||
|
|
658f946202 | ||
|
|
dfa40c79b0 | ||
|
|
93f7a32ea5 | ||
|
|
656eb06159 | ||
|
|
e66a3ac883 | ||
|
|
aba34f0648 | ||
|
|
9890b4939b | ||
|
|
5b9ff7d457 | ||
|
|
22fdbaad41 | ||
|
|
80cd0ebc4d | ||
|
|
b525d8dc23 | ||
|
|
0c3bc30439 | ||
|
|
945ccc874d | ||
|
|
fef139be64 | ||
|
|
e506edc965 | ||
|
|
f10a383e36 | ||
|
|
21f0d9dd05 | ||
|
|
d81f9ca2bb | ||
|
|
3a3860f617 | ||
|
|
e7eea495ff | ||
|
|
7b3c662dcb | ||
|
|
6812c001de | ||
|
|
266b90e8ce | ||
|
|
21cc6d6021 | ||
|
|
ce40aa1ba9 | ||
|
|
33bc54480d | ||
|
|
d7f673cb32 | ||
|
|
0f269fb2da | ||
|
|
89e5eeaa61 | ||
|
|
58446d1511 | ||
|
|
4cb1cd6e57 | ||
|
|
8ef011145c | ||
|
|
68fb1c3655 | ||
|
|
1d844bfa1c | ||
|
|
68b6d0a047 | ||
|
|
734ec616cc |
2
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
liberapay: gdb
|
||||
custom: 'https://www.paypal.me/gdbau'
|
||||
54
.github/ISSUE_TEMPLATE/issue.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: Issue
|
||||
about: Open an issue for help, to report a bug, or request a feature
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# `alsa-scarlett-gui` Issue Template
|
||||
|
||||
Thank you for taking the time to contribute to the `alsa-scarlett-gui` project. Before you submit your issue, please ensure you have checked the FAQ and provide the necessary information below.
|
||||
|
||||
## Confirmation
|
||||
- [ ] I confirm that I have read the [FAQ](https://github.com/geoffreybennett/alsa-scarlett-gui/blob/master/FAQ.md).
|
||||
|
||||
## Issue Category
|
||||
Please select the category that best describes your issue:
|
||||
- [ ] Help Request
|
||||
- [ ] Bug Report
|
||||
- [ ] Feature Request
|
||||
|
||||
## Environment Details
|
||||
Please provide the following details about your environment.
|
||||
|
||||
### Linux Distribution and Version
|
||||
(paste output from `cat /etc/redhat-release` or `cat /etc/lsb_release` here)
|
||||
- Distribution:
|
||||
- Version:
|
||||
|
||||
### Kernel Version
|
||||
(paste output from `uname -r` here)
|
||||
- Kernel version:
|
||||
|
||||
### Kernel Messages
|
||||
(paste output from `dmesg | grep -A 5 -B 5 -i focusrite` here)
|
||||
|
||||
### Focusrite Interface Series and Model
|
||||
(maybe shown in kernel messages, or paste output from `lsusb -d1235:` if unsure)
|
||||
- Series (e.g., Scarlett 2nd/3rd/4th Gen, Clarett USB, Clarett+):
|
||||
- Model (e.g., Solo, 2i2, 4i4, etc.):
|
||||
|
||||
### Audio System
|
||||
(use `ps aux | grep -E "pulseaudio|jackd|pipewire"` to check)
|
||||
- [ ] PulseAudio
|
||||
- [ ] JACK
|
||||
- [ ] PipeWire
|
||||
|
||||
## Issue Description
|
||||
Please provide a detailed description of the issue or feature request, including steps to reproduce (if applicable), expected behavior, and actual behavior:
|
||||
|
||||
---
|
||||
|
||||
Thank you for helping improve `alsa-scarlett-gui`!
|
||||
9
.github/workflows/build-debian-package.yml
vendored
@@ -19,11 +19,11 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt -y update
|
||||
sudo apt -y install git make gcc libgtk-4-dev libasound2-dev
|
||||
sudo apt -y install git make gcc libgtk-4-dev libasound2-dev libssl-dev
|
||||
|
||||
- name: Build from sources
|
||||
run: |
|
||||
make -C src -j4 PREFIX=/usr
|
||||
make -C src -j$(nproc) PREFIX=/usr
|
||||
|
||||
- name: Prepare package workspace
|
||||
run: |
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
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/vu.b4.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 }}/
|
||||
cp -r *.md demo docs img ${{ github.workspace }}/deb-workspace/usr/share/doc/${{ env.APP_NAME }}-${{ env.APP_VERSION }}/
|
||||
|
||||
- name: Build debian package
|
||||
uses: jiro4989/build-deb-action@v2
|
||||
@@ -42,8 +42,9 @@ jobs:
|
||||
package: ${{ env.APP_NAME }}
|
||||
package_root: ${{ github.workspace }}/deb-workspace
|
||||
maintainer: geoffreybennett
|
||||
depends: 'libgtk-4-1, libasound2, alsa-utils'
|
||||
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.
|
||||
desc: ${{ env.APP_NAME }} is a Gtk4 GUI for the ALSA controls presented by the Linux kernel Focusrite USB drivers.
|
||||
|
||||
- name: Upload Release Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
|
||||
2
.github/workflows/build-flatpak-package.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
name: "Flatpak"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-45
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-47
|
||||
options: --privileged
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
154
FAQ.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# FAQ for the ALSA Scarlett Control Panel (`alsa-scarlett-gui`)
|
||||
|
||||
## What is this?
|
||||
|
||||
The ALSA Scarlett Control Panel (`alsa-scarlett-gui`) is an
|
||||
easy-to-use application for adjusting the ALSA controls provided by
|
||||
three Linux kernel drivers for Focusrite USB interfaces:
|
||||
|
||||
1. The Scarlett 1st Gen Mixer Driver (for 1st Gen 6i6, 8i6, 18i6, 18i8, 18i20)
|
||||
2. The Scarlett2 Protocol Driver (for 2nd/3rd Gen interfaces, small 4th Gen, Clarett, and Vocaster)
|
||||
3. The FCP (Focusrite Control Protocol) Driver (for big 4th Gen interfaces: 16i16, 18i16, 18i20)
|
||||
|
||||
To check if your kernel is already up-to-date, and how to upgrade if
|
||||
not, see the [Control Panel Installation Prerequisites — Linux
|
||||
Kernel](docs/INSTALL.md).
|
||||
|
||||
## Do I need these drivers for my Focusrite interface?
|
||||
|
||||
For basic audio functionality? No. Focusrite USB interfaces are
|
||||
“plug-and-play” — they are USB Audio Class Compliant, meaning they
|
||||
work out-of-the-box with the standard ALSA USB audio driver (to get
|
||||
full functionality on Scarlett 3rd/4th Gen/Vocaster interfaces, first
|
||||
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.
|
||||
|
||||
## MSD Mode?
|
||||
|
||||
"MSD Mode" is the "Mass Storage Device Mode" that the Scarlett 3rd and
|
||||
4th Gen interfaces ship in.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
You can turn off MSD Mode by holding down the 48V button while
|
||||
powering on the interface, or by clicking the button in
|
||||
`alsa-scarlett-gui` and rebooting it.
|
||||
|
||||
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?
|
||||
|
||||
These drivers are for users who want more control over their
|
||||
interface. They allow for detailed manipulation of:
|
||||
|
||||
- Internal audio routing
|
||||
- Hardware-specific settings
|
||||
- Mixer functionality
|
||||
- Level monitoring
|
||||
- Input/output configuration
|
||||
|
||||
These controls go beyond the basic audio I/O functionality provided by
|
||||
the generic ALSA USB audio driver.
|
||||
|
||||
## What interfaces are supported?
|
||||
|
||||
The ALSA Scarlett Control Panel supports:
|
||||
|
||||
- **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 USB and Clarett+**: 2Pre, 4Pre, 8Pre
|
||||
- **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
|
||||
GUI.
|
||||
|
||||
## Where are the options to set the sample rate and buffer size?
|
||||
|
||||
The ALSA Scarlett Control Panel doesn’t 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.
|
||||
|
||||
The sample rate shown in the control panel is informative only and
|
||||
displays the current rate being used by applications. If it shows
|
||||
“N/A” then no application is using the interface.
|
||||
|
||||
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 interface’s 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? It’s 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
|
||||
|
||||
For help with the FCP user-space side:
|
||||
https://github.com/geoffreybennett/fcp-support/issues
|
||||
|
||||
For help with `alsa-scarlett-gui`:
|
||||
https://github.com/geoffreybennett/alsa-scarlett-gui/issues
|
||||
|
||||
For general Linux audio help: https://linuxmusicians.com
|
||||
158
INSTALL.md
@@ -1,158 +0,0 @@
|
||||
# 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 you’ll 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
|
||||
```
|
||||
413
INTERFACES.md
@@ -1,413 +0,0 @@
|
||||
# Focusrite Scarlett Interface Features by Model
|
||||
|
||||
The information here was compiled carefully and is believed accurate
|
||||
but there might still be mistakes. Please independently confirm before
|
||||
relying on anything here.
|
||||
|
||||
## 6i6 Gen 2
|
||||
|
||||
- 6× Hardware Inputs
|
||||
- Analogue In 1–2: Mic/Line/Inst In 1–2 (Pad)
|
||||
- Analogue In 3–4: Line In 3–4
|
||||
- S/PDIF 1–2
|
||||
|
||||
- Hardware Input Controls
|
||||
- 2× Input Gain knobs for Analogue In 1–2
|
||||
- Fixed Input Gain for Analogue In 3–4
|
||||
- Phantom Power for Analogue 1–2 linked
|
||||
|
||||
- 6× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L) + Headphone 1 Left
|
||||
- Analogue 2: Line 2 Out (Monitor R) + Headphone 1 Right
|
||||
- Analogue 3: Line 3 Out + Headphone 2 Left
|
||||
- Analogue 4: Line 4 Out + Headphone 2 Right
|
||||
- S/PDIF 1–2
|
||||
|
||||
- Hardware Output Controls
|
||||
- Monitor volume knob controlling Line 1+2
|
||||
- No physical control for Line 3+4 output volume
|
||||
- Headphone 1 volume knob controlling Headphone 1 Volume
|
||||
- Headphone 2 volume knob controlling Headphone 2 Volume
|
||||
- 4× Mute + Line Out Gain controls −127dB to 0dB
|
||||
- 1–2 control Line 1–2 Out and Headphone 1
|
||||
- 3–4 control Line 3–4 Out and Headphone 2
|
||||
|
||||
- Mixer: 18 input (1–18), 10 output (A–J)
|
||||
- 18×10 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 6× PCM Inputs (USB device to host)
|
||||
|
||||
- 6× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–4, S/PDIF 1–2, Mix A–J, PCM Outputs 1–6
|
||||
|
||||
- Sync Status
|
||||
|
||||
- Clock Source: Internal or S/PDIF
|
||||
|
||||
## 18i8 Gen 2
|
||||
|
||||
- 18× Hardware Inputs
|
||||
- Analogue 1–2: Mic/Line/Inst In 1–2 (Pad)
|
||||
- Analogue 3–4: Mic/Line In 3–4 (Pad)
|
||||
- Analogue 5–8: Line In 5–8
|
||||
- S/PDIF 1–2
|
||||
- ADAT 1–8
|
||||
|
||||
- Hardware Input Controls
|
||||
- 4× Input Gain knobs for Analogue In 1–4
|
||||
- Fixed Input Gain for Analogue In 5–8
|
||||
- Phantom Power for Analogue 1–2 linked
|
||||
- Phantom Power for Analogue 3–4 linked
|
||||
|
||||
- 8× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L)
|
||||
- Analogue 2: Line 2 Out (Monitor R)
|
||||
- Analogue 3: Headphone 1 Left
|
||||
- Analogue 4: Headphone 1 Right
|
||||
- Analogue 5: Headphone 2 Left
|
||||
- Analogue 6: Headphone 2 Right
|
||||
- S/PDIF 1–2
|
||||
|
||||
- Hardware Output Controls
|
||||
- Monitor volume knob controlling Line 1+2
|
||||
- Headphone 1 volume knob controlling Headphone 1 Volume
|
||||
- Headphone 2 volume knob controlling Headphone 2 Volume
|
||||
- 6× Mute + Line Out Gain controls −127dB to 0dB
|
||||
- 1–2 control Line 1–2 Out
|
||||
- 3–4 control Headphone 1
|
||||
- 5–6 control Headphone 2
|
||||
|
||||
- Mixer: 20 input (1–20), 10 output (A–J)
|
||||
- 20×10 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 20× PCM Inputs (USB device to host)
|
||||
|
||||
- 8× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–8, S/PDIF 1–2, ADAT 1–8, Mix A–J, PCM
|
||||
Outputs 1–8
|
||||
|
||||
- Sync Status
|
||||
|
||||
- Clock Source: Internal, S/PDIF, or ADAT
|
||||
|
||||
## 18i20 Gen 2
|
||||
|
||||
- 18× Hardware Inputs
|
||||
- Analogue 1–2: Mic/Line/Inst In 1–2 (Pad)
|
||||
- Analogue 3–8: Mic/Line In 3–8
|
||||
- S/PDIF 1–2
|
||||
- ADAT 1–8
|
||||
|
||||
- Hardware Input Controls
|
||||
- 8× Input Gain knobs for Analogue In 1–8
|
||||
- Phantom Power for Analogue 1–4 linked
|
||||
- Phantom Power for Analogue 5–8 linked
|
||||
|
||||
- 20× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L)
|
||||
- Analogue 2: Line 2 Out (Monitor R)
|
||||
- Analogue 3: Line 3 Out
|
||||
- Analogue 4: Line 4 Out
|
||||
- Analogue 5: Line 5 Out
|
||||
- Analogue 6: Line 6 Out
|
||||
- Analogue 7: Line 7 Out + Headphone 1 Left
|
||||
- Analogue 8: Line 8 Out + Headphone 1 Right
|
||||
- Analogue 9: Line 9 Out + Headphone 2 Left
|
||||
- Analogue 10: Line 10 Out + Headphone 2 Right
|
||||
- S/PDIF 1–2
|
||||
- ADAT 1–8
|
||||
|
||||
- Hardware Output Controls
|
||||
- For Analogue 1–8 Outputs:
|
||||
- 8× SW/HW Volume Control Switch
|
||||
- 8× SW Line Out Gain controls −127dB to 0dB
|
||||
- 8× SW Mute
|
||||
- Monitor volume knob controlling volume of Analogue 1–8 (selected
|
||||
by SW/HW Volume Control Switches)
|
||||
- Global Mute and Dim controlling Analogue 1–8 (enabled per-channel
|
||||
if SW/HW Volume Control Switch set to HW)
|
||||
- 2× Headphone volume knob controlling Headphone volume (applied in
|
||||
addition to the SW/HW Volume Control)
|
||||
|
||||
- Mixer: 20 input (1–20), 10 output (A–J)
|
||||
- 20×10 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 20× PCM Inputs (USB device to host)
|
||||
|
||||
- 18× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–8, S/PDIF 1–2, ADAT 1–8, Mix A–J, PCM
|
||||
Outputs 1–8
|
||||
|
||||
- Sync Status
|
||||
|
||||
- Clock Source: Internal, S/PDIF, or ADAT
|
||||
|
||||
## Solo Gen 3
|
||||
|
||||
- 2× Hardware Inputs
|
||||
- Analogue In 1: Mic In (Air, Phantom Power)
|
||||
- Analogue In 2: Line/Inst In
|
||||
|
||||
- Hardware Input Controls
|
||||
- 2× Input Gain knobs for Analogue 1–2
|
||||
- Phantom Power Persistence
|
||||
|
||||
- 2× Hardware Outputs
|
||||
- Analogue Out 1: Line Out Left + Headphone Left
|
||||
- Analogue Out 2: Line Out Right + Headphone Right
|
||||
|
||||
- Hardware Output Controls
|
||||
- Monitor volume knob controls all outputs together
|
||||
|
||||
- 2× PCM Inputs (USB device to host)
|
||||
- Fixed to Analogue Inputs 1–2
|
||||
|
||||
- 2× PCM Outputs (USB host to device)
|
||||
- Fixed to Analogue Outputs 1–2
|
||||
|
||||
- Direct Monitor:
|
||||
- On: mixes Analogue 1+2 Inputs into both Analogue 1+2 Outputs
|
||||
|
||||
## 2i2 Gen 3
|
||||
|
||||
- 2× Hardware Inputs
|
||||
- Analogue In 1–2: Mic/Line/Inst In 1–2 (Air)
|
||||
|
||||
- Hardware Input Controls
|
||||
- 2× Input Gain knobs for Analogue 1–2
|
||||
- Phantom Power for Analogue 1–2 linked
|
||||
- Phantom Power Persistence
|
||||
|
||||
- 2× Hardware Outputs
|
||||
- Analogue Out 1: Line Out Left + Headphone Left
|
||||
- Analogue Out 2: Line Out Right + Headphone Right
|
||||
|
||||
- Hardware Output Controls
|
||||
- Monitor volume knob for Line Out Left and Right
|
||||
- Headphone volume knob for Headphone
|
||||
|
||||
- 2× PCM Inputs (USB device to host)
|
||||
- Fixed to Analogue Inputs 1–2
|
||||
|
||||
- 2× PCM Outputs (USB host to device)
|
||||
- Fixed to Analogue Outputs 1–2
|
||||
|
||||
- Direct Monitor:
|
||||
- Mono: mixes both Analogue 1+2 Inputs into both Analogue 1+2
|
||||
Outputs
|
||||
- Stereo: mixes Analogue 1+2 Inputs into Analogue 1+2 Outputs
|
||||
respectively
|
||||
|
||||
## 4i4 Gen 3
|
||||
|
||||
- 4× Hardware Inputs
|
||||
- Analogue In 1–2: Mic/Line/Inst In 1–2 (Air, Pad)
|
||||
- Analogue In 3–4: Line In 3–4
|
||||
|
||||
- Hardware Input Controls
|
||||
- 2× Input Gain knobs for Analogue In 1–2
|
||||
- Fixed Input Gain for Analogue In 3–4
|
||||
- Phantom Power for Analogue 1–2 linked
|
||||
- Phantom Power Persistence
|
||||
|
||||
- 4× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L)
|
||||
- Analogue 2: Line 2 Out (Monitor R)
|
||||
- Analogue 3: Line 3 Out + Headphone Left
|
||||
- Analogue 4: Line 4 Out + Headphone Right
|
||||
|
||||
- Hardware Output Controls
|
||||
- Monitor volume knob controlling Line 1+2
|
||||
- Headphone volume knob controlling Headphone volume
|
||||
- No physical control for Line 3+4 output volume
|
||||
- 4× Mute + Line Out Gain controls −127dB to 0dB
|
||||
- 1–2 control Line 1–2 Out
|
||||
- 3–4 control Line 3–4 Out and Headphone
|
||||
|
||||
- Mixer: 8 input (1–8), 6 output (A–F)
|
||||
- 8×6 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 6× PCM Inputs (USB device to host)
|
||||
|
||||
- 4× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–4, Mix A–F, PCM Outputs 1–4
|
||||
|
||||
- Sync Status
|
||||
|
||||
## 8i6 Gen 3
|
||||
|
||||
- 8× Hardware Inputs
|
||||
- Analogue 1–2: Mic/Line/Inst In 1–2 (Air, Pad)
|
||||
- Analogue 3–6: Line In 3–6
|
||||
- S/PDIF 1–2
|
||||
|
||||
- Hardware Input Controls
|
||||
- 2× Input Gain knobs for Analogue In 1–2
|
||||
- Fixed Input Gain for Analogue In 3–6
|
||||
- Phantom Power for Analogue 1–2 linked
|
||||
- Phantom Power Persistence
|
||||
|
||||
- 6× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L) + Headphone 1 Left
|
||||
- Analogue 2: Line 2 Out (Monitor R) + Headphone 1 Right
|
||||
- Analogue 3: Line 3 Out + Headphone 2 Left
|
||||
- Analogue 4: Line 4 Out + Headphone 2 Right
|
||||
- S/PDIF 1–2
|
||||
|
||||
- Hardware Output Controls
|
||||
- Monitor volume knob controlling Line 1+2
|
||||
- No physical control for Line 3+4 output volume
|
||||
- Headphone 1 volume knob controlling Headphone 1 Volume
|
||||
- Headphone 2 volume knob controlling Headphone 2 Volume
|
||||
- 4× Line Out Gain controls −127dB to 0dB
|
||||
- 1–2 control Line 1–2 Out and Headphone 1
|
||||
- 3–4 control Line 3–4 Out and Headphone 2
|
||||
|
||||
- Mixer: 8 input (1–8), 8 output (A–H)
|
||||
- 8×8 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 10× PCM Inputs (USB device to host)
|
||||
|
||||
- 6× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–6, S/PDIF 1–2, Mix A–H, PCM Outputs 1–6
|
||||
|
||||
- Sync Status
|
||||
|
||||
- Clock Source: Internal or S/PDIF
|
||||
|
||||
## 18i8 Gen 3
|
||||
|
||||
- 18× Hardware Inputs
|
||||
- Analogue 1–2: Mic/Line/Inst In 1–2 (Air, Pad)
|
||||
- Analogue 3–4: Mic/Line In 3–4 (Air, Pad)
|
||||
- Analogue 5–8: Line In 5–8
|
||||
- S/PDIF 1–2
|
||||
- ADAT 1–8
|
||||
|
||||
- Hardware Input Controls
|
||||
- 4× Input Gain knobs for Analogue In 1–4
|
||||
- Fixed Input Gain for Analogue In 5–8
|
||||
- Phantom Power for Analogue 1–2 linked
|
||||
- Phantom Power for Analogue 3–4 linked
|
||||
- Phantom Power Persistence
|
||||
|
||||
- 10× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L)
|
||||
- Analogue 2: Line 2 Out (Monitor R)
|
||||
- Analogue 3: Line 3 Out (Alt Monitor L)
|
||||
- Analogue 4: Line 4 Out (Alt Monitor R)
|
||||
- Analogue 5: Headphone 1 Left
|
||||
- Analogue 6: Headphone 1 Right
|
||||
- Analogue 7: Headphone 2 Left
|
||||
- Analogue 8: Headphone 2 Right
|
||||
- S/PDIF 1–2
|
||||
|
||||
Note: The Headphones outputs are internally Analogue 3–6 and the rear
|
||||
Line 3/4 outputs (Alt Monitor) are internally Analogue 7/8, but the
|
||||
driver hides this from you.
|
||||
|
||||
- Hardware Output Controls
|
||||
- For Analogue 1–8 Outputs:
|
||||
- 8× SW/HW Volume Control Switch
|
||||
- 8× SW Line Out Gain controls −127dB to 0dB
|
||||
- 8× SW Mute
|
||||
- Monitor volume knob controlling volume of Analogue 1–8 (selected
|
||||
by SW/HW Volume Control Switches)
|
||||
- Global mute and dim controlling Analogue 1–8 (enabled per-channel
|
||||
if SW/HW Volume Control Switch set to HW)
|
||||
- 2× Headphone volume knob controlling Headphone volume (applied in
|
||||
addition to the SW/HW Volume Control)
|
||||
|
||||
- Mixer: 18 input (1–18), 10 output (A–J)
|
||||
- 18×10 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 18× PCM Inputs (USB device to host)
|
||||
|
||||
- 8× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–8, S/PDIF 1–2, ADAT 1–8, Mix A–J, PCM
|
||||
Outputs 1–20
|
||||
|
||||
- Speaker Switching
|
||||
|
||||
- Sync Status
|
||||
|
||||
- Clock Source: Internal, S/PDIF, or ADAT
|
||||
|
||||
## 18i20 Gen 3
|
||||
|
||||
- 19× Hardware Inputs
|
||||
- Analogue 1–2: Mic/Line/Inst In 1–2 (Air, Pad)
|
||||
- Analogue 3–8: Mic/Line In 3–8 (Air, Pad)
|
||||
- Analogue 9: Talkback Mic
|
||||
- S/PDIF 1–2
|
||||
- ADAT 1–8
|
||||
|
||||
- Hardware Input Controls
|
||||
- 8× Input Gain knobs for Analogue In 1–8
|
||||
- Phantom Power for Analogue 1–4 linked
|
||||
- Phantom Power for Analogue 5–8 linked
|
||||
- Phantom Power Persistence
|
||||
|
||||
- 20× Hardware Outputs
|
||||
- Analogue 1: Line 1 Out (Monitor L)
|
||||
- Analogue 2: Line 2 Out (Monitor R)
|
||||
- Analogue 3: Line 3 Out
|
||||
- Analogue 4: Line 4 Out
|
||||
- Analogue 5: Line 5 Out
|
||||
- Analogue 6: Line 6 Out
|
||||
- Analogue 7: Line 7 Out + Headphone 1 Left
|
||||
- Analogue 8: Line 8 Out + Headphone 1 Right
|
||||
- Analogue 9: Line 9 Out + Headphone 2 Left
|
||||
- Analogue 10: Line 10 Out + Headphone 2 Right
|
||||
- S/PDIF 1–2
|
||||
- ADAT 1–8
|
||||
|
||||
- Hardware Output Controls
|
||||
- For Analogue 1–8 Outputs:
|
||||
- 8× SW/HW Volume Control Switch
|
||||
- 8× SW Line Out Gain controls −127dB to 0dB
|
||||
- 8× SW Mute
|
||||
- Monitor volume knob controlling volume of Analogue 1–8 (selected
|
||||
by SW/HW Volume Control Switches)
|
||||
- Global Mute and Dim controlling Analogue 1–8 (enabled per-channel
|
||||
if SW/HW Volume Control Switch set to HW)
|
||||
- 2× Headphone volume knob controlling Headphone volume (applied in
|
||||
addition to the SW/HW Volume Control)
|
||||
|
||||
- Mixer: 25 input (1–25), 12 output (A–L)
|
||||
- 25×12 gain controls −80dB to +6dB
|
||||
- Each input assignable to any of the assignable outputs
|
||||
|
||||
- 20× PCM Inputs (USB device to host)
|
||||
|
||||
- 20× PCM Outputs (USB host to device)
|
||||
|
||||
- Assignable outputs to the hardware outputs, mixer, and PCM Inputs:
|
||||
- Off, Analogue Inputs 1–8, S/PDIF 1–2, ADAT 1–8, Mix A–L, PCM
|
||||
Outputs 1–8
|
||||
|
||||
- Speaker Switching
|
||||
|
||||
- Talkback Mic
|
||||
|
||||
- Sync Status
|
||||
|
||||
- Clock Source: Internal, S/PDIF, or ADAT
|
||||
2
Makefile
@@ -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:"
|
||||
|
||||
99
README.md
@@ -1,97 +1,8 @@
|
||||
# ALSA Scarlett Gen 2/3 Control Panel (`alsa-scarlett-gui`)
|
||||
# ALSA Scarlett 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/Clarett USB/Clarett+ Mixer
|
||||
Driver.
|
||||
- Upstream project here: https://github.com/geoffreybennett/alsa-scarlett-gui
|
||||
- Debian's packaged version here: https://salsa.debian.org/doge-tech/alsa-scarlett-gui
|
||||
|
||||
## About
|
||||
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.
|
||||
|
||||
<img src="src/img/alsa-scarlett-gui-logo.png" align="right">
|
||||
|
||||
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 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 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 (and Clarett USB/Clarett+!)
|
||||
Control Panel!
|
||||
|
||||

|
||||
|
||||
The GUI supports all features presented by the driver (if not, please
|
||||
report a bug).
|
||||
|
||||
## Documentation
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
## 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-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
|
||||
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.
|
||||
|
||||
379
USAGE.md
@@ -1,379 +0,0 @@
|
||||
# ALSA Scarlett Gen 2/3 Control Panel Usage
|
||||
|
||||
Refer to [INSTALL.md](INSTALL.md) for prerequisites, how to build,
|
||||
install, and run.
|
||||
|
||||
For usage instructions, read on...
|
||||
|
||||
## No interface connected
|
||||
|
||||
If no interface is detected (usually because there isn’t one
|
||||
connected!) you’ll see this window:
|
||||
|
||||

|
||||
|
||||
Plug in an interface or select the menu option File → Interface
|
||||
Simulation and load a demo file to make more interesting things
|
||||
happen.
|
||||
|
||||
## MSD (Mass Storage Device) Mode
|
||||
|
||||
If MSD Mode is enabled (as it is from the factory), you need to
|
||||
disable it and restart your interface to get access to its full
|
||||
functionality.
|
||||
|
||||

|
||||
|
||||
## Using on Small Interfaces
|
||||
|
||||
For the small Gen 3 interfaces (Solo and 2i2), there’s just a few
|
||||
buttons to control the Air, Line, Phantom Power, and Direct Monitor
|
||||
settings. Mostly nothing that you can’t access from the front panel
|
||||
anyway.
|
||||
|
||||

|
||||
|
||||
The Line/Inst (Level), Air, and 48V controls are described below in
|
||||
the Analogue Input Controls section.
|
||||
|
||||
Direct Monitor sends the analogue input signals to the analogue
|
||||
outputs for zero-latency monitoring. On the 2i2, you have the choice
|
||||
of Mono or Stereo monitoring. Mono sends both inputs to the left and
|
||||
right outputs. Stereo sends input 1 to the left, and input 2 to the
|
||||
right output.
|
||||
|
||||
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+, Gen 3 4i4+, Clarett USB, and Clarett+ Interfaces
|
||||
|
||||
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
|
||||
- Analogue Input Controls
|
||||
- Analogue Output Controls
|
||||
|
||||

|
||||
|
||||
The View menu option on the main window lets you open three other
|
||||
windows which contain the other controls:
|
||||
- Routing
|
||||
- Mixer
|
||||
- Startup
|
||||
|
||||
### Global Controls
|
||||
|
||||
Global controls affect 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.
|
||||
|
||||
#### 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 Sync Status
|
||||
is Unlocked, change the Clock Source to Internal.
|
||||
|
||||
#### Speaker Switching (18i8 Gen 3 and 18i20 Gen 3 only)
|
||||
|
||||
Speaker Switching lets you swap between two pairs of monitoring
|
||||
speakers very easily.
|
||||
|
||||
When enabled (Main or Alt):
|
||||
|
||||
- Line Out 1–4 Volume Control Switches are locked to HW
|
||||
- Line Out 3/4 routing is saved
|
||||
- Line Out 3/4 routing is set to the Line Out 1/2 routing
|
||||
|
||||
When set to Main, Line outputs 3 and 4 are muted.
|
||||
|
||||
When set to Alt, Line outputs 1 and 2 are muted.
|
||||
|
||||
When disabled (Off):
|
||||
- Global mute is activated
|
||||
- Line Out 1–4 Volume Control Switches are unlocked
|
||||
- Line Out 3/4 routing is restored to the saved values
|
||||
|
||||
#### Talkback (18i20 Gen 3 only)
|
||||
|
||||
Talkback lets you add another channel (usually the talkback mic) to a
|
||||
mix with a button push, usually to talk to musicians, and without
|
||||
using an additional mic channel.
|
||||
|
||||
The Talkback feature has a few parts:
|
||||
|
||||
- Talkback Microphone connected to Analogue Input 9
|
||||
- Talkback Disable/Enable internal switch
|
||||
- Talkback Off/On physical switch
|
||||
- Talkback Mix (one switch per mix)
|
||||
- Mix Input 25
|
||||
|
||||
To set up the talkback feature, set Mix Input 25 to the talkback
|
||||
source (usually Analogue Input 9), enable the Talkback Mix switches
|
||||
for the mixes you want the talkback input to be heard on, and change
|
||||
the Talkback control from Disabled to Off. Leave the Mix Input 25 gain
|
||||
controls at zero (−127dB), otherwise the talkback inputs will be heard
|
||||
even when talkback is disabled/off.
|
||||
|
||||
Pressing the Talkback switch on the device will then lower the volume
|
||||
of the other inputs on the mixes for which talkback is enabled and
|
||||
unmute Mix Input 25 on those mixes.
|
||||
|
||||
Talkback can also be activated by changing the Talkback control from
|
||||
Off to On.
|
||||
|
||||
The talkback microphone can also be used just the same as any of the
|
||||
other analogue inputs and routed to a physical output, PCM input, or
|
||||
mixer input.
|
||||
|
||||
### Analogue Input Controls
|
||||
|
||||
This is applicable to all interfaces except the Gen 2 18i20 which has
|
||||
hardware-only buttons for these features.
|
||||
|
||||
#### Level
|
||||
|
||||
The Level buttons are used to select between Mic/Line and Instrument
|
||||
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, Clarett USB, and Clarett+ only)
|
||||
|
||||
Enabling Air will transform your recordings and inspire you while
|
||||
making music.
|
||||
|
||||
#### Pad
|
||||
|
||||
Enabling Pad engages an attenuator in the channel, giving you more
|
||||
headroom for very hot signals.
|
||||
|
||||
#### Phantom Power (48V)
|
||||
|
||||
Gen 2 devices have a hardware button for controlling phantom power.
|
||||
|
||||
Gen 3 devices have hardware and software control of phantom power.
|
||||
Turning the “48V” switch on sends “Phantom Power” to the XLR
|
||||
microphone input. This is required for some microphones (such as
|
||||
condensor microphones), and damaging to some microphones (particularly
|
||||
vintage ribbon microphones).
|
||||
|
||||
On Gen 3 device, phantom power is turned off by default when the
|
||||
interface is turned on. This can be changed in the startup
|
||||
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 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
|
||||
wheel. You can also double-click on the volume dial to quickly toggle
|
||||
the volume between the minimum value and 0dB.
|
||||
|
||||
The bigger interfaces: Gen 2 18i20, Gen 3 18i8, and Gen 3 18i20 have a
|
||||
switchable hardware/software volume control. The position of the big
|
||||
volume knob on the front of the interface is indicated by the “HW”
|
||||
dial in the GUI. The analogue outputs can have their volume set either
|
||||
by the knob (“HW” setting of of the HW/SW button) or by the dials on
|
||||
each output (“SW” setting of the HW/SW button).
|
||||
|
||||
When set to HW, the mute/volume status for those channels is
|
||||
controlled by the hardware volume knob and the global dim/mute
|
||||
controls and the software volume dial and mute button for those
|
||||
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 doesn’t have physical buttons or indicator lights for these
|
||||
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
|
||||
in addition to the software volume control, therefore both must be
|
||||
turned up in order to hear anything. The other (line 3+) analogue
|
||||
outputs are only controlled by the software controls.
|
||||
|
||||
The volume controls for the headphone outputs on each interface
|
||||
operate in addition to any other hardware or software volume controls
|
||||
for those channels. When using headphones, the volumes for those
|
||||
channels would usually be set to 0dB and the actual volume controlled
|
||||
with the physical headphone volume control(s).
|
||||
|
||||
### Routing
|
||||
|
||||
The routing window allows complete control of signal routing between
|
||||
the hardware inputs/outputs, internal mixer, and PCM (USB)
|
||||
inputs/outputs.
|
||||
|
||||

|
||||
|
||||
To manage the routing connections:
|
||||
|
||||
- Click and drag from a source to a sink or a sink to a source to
|
||||
connect them. Audio from the source will then be sent to that sink.
|
||||
|
||||
- Click on a source or a sink to clear the links connected to that
|
||||
source/sink.
|
||||
|
||||
Note that a sink can only be connected to one source, but one source
|
||||
can be connected to many sinks. If you want a sink to receive input
|
||||
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
|
||||
interface as an 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 Outputs.
|
||||
|
||||
- The “Stereo Out” preset connects PCM 1 and 2 Outputs to pairs of
|
||||
Hardware Outputs.
|
||||
|
||||
The Direct routing configuration is the simplest most-generally-useful
|
||||
configuration:
|
||||
|
||||

|
||||
|
||||
#### Loopback
|
||||
|
||||
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 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.
|
||||
|
||||
#### Talkback
|
||||
|
||||
The Gen 3 18i20 talkback microphone is Analogue Input 9 and can be
|
||||
routed like any other source. If you want to record using it, there is
|
||||
no need for the loopback hack suggested by the vendor. Just route it
|
||||
to a PCM Input.
|
||||
|
||||
### Mixer
|
||||
|
||||
If you use the Routing window to connect Sources to Mixer Inputs and
|
||||
Mixer Outputs to Sinks, 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:
|
||||
|
||||

|
||||
|
||||
Click and drag up/down on the gain controls to adjust, or use your
|
||||
mouse scroll wheel. You can also double-click on the dial to quickly
|
||||
toggle between the minimum value and 0dB.
|
||||
|
||||
### Startup
|
||||
|
||||
The Startup window is used to configure settings that only take effect
|
||||
when the interface is powered on.
|
||||
|
||||

|
||||
|
||||
#### Standalone
|
||||
|
||||
When Standalone mode is enabled, the interface will continue to route
|
||||
audio as per the previous routing and mixer settings after it has been
|
||||
disconnected from a computer. By configuring the routing between the
|
||||
hardware and mixer inputs and outputs appropriately, the interface can
|
||||
act as a standalone preamp or mixer.
|
||||
|
||||
Standalone mode is supported on all devices supported by the kernel
|
||||
driver. Even the 4i4 Gen 3 (which is bus-powered) will operate in
|
||||
standalone mode.
|
||||
|
||||
#### Phantom Power Persistence (Gen 3 only)
|
||||
|
||||
When Phantom Power Persistence is enabled, the interface will restore
|
||||
the previous Phantom Power/48V setting when the interface is turned
|
||||
on. For the safety of microphones which can be damaged by phantom
|
||||
power, the interface defaults to having phantom power disabled when it
|
||||
is turned on.
|
||||
|
||||
#### MSD (Mass Storage Device) Mode (Gen 3 only)
|
||||
|
||||
When MSD Mode is enabled (as it is from the factory), the interface
|
||||
has reduced functionality. You’ll want to have this disabled. On the
|
||||
other hand, when MSD Mode is enabled, the interface presents itself as
|
||||
a Mass Storage Device (like a USB stick), containing a link to the
|
||||
Focusrite web site encouraging you to register your product and
|
||||
download the proprietary drivers which can’t be used on Linux.
|
||||
|
||||
By default, once MSD Mode is disabled, the control for it is hidden.
|
||||
If for some reason you want to re-enable MSD Mode, you can set the
|
||||
`device_setup` option to 3 to get the control back.
|
||||
|
||||
## Load/Save Configuration
|
||||
|
||||
The entire state of the interface can be loaded and saved using the
|
||||
File → Load Configuration and File → Save Configuration menu options.
|
||||
|
||||
Internally, this uses `alsactl`:
|
||||
|
||||
- Load: `alsactl restore USB -f <fn>`
|
||||
- Save: `alsactl store USB -f <fn>`
|
||||
|
||||
The saved state files can be used to simulate an interface if you
|
||||
don’t have one attached. The `demo` directory in the distribution
|
||||
contains a sample file for every supported model.
|
||||
|
||||
## Interface Simulation Mode
|
||||
|
||||
The GUI can load an `alsactl` state file saved from a real interface
|
||||
and display a GUI as if the corresponding interface was connected.
|
||||
|
||||
This is useful if you don’t have an interface connected and want to
|
||||
try, develop, or debug the GUI.
|
||||
|
||||
Either specify the `.state` filename on the command line or select the
|
||||
menu option File → Interface Simulation to load.
|
||||
|
||||
## Known Bugs/Issues
|
||||
|
||||
- The linear-dB scale of the volume controls doesn’t work well. Lower
|
||||
volumes (e.g. below −30dB) don’t need as much fine control as higher
|
||||
volumes.
|
||||
|
||||
- Can’t select (focus) the gain/volume controls or use a keyboard to
|
||||
adjust them.
|
||||
|
||||
- Level meters don’t 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.
|
||||
|
||||
- Load/Save is not implemented for simulated interfaces.
|
||||
|
||||
- Lots of “couldn't find weak ref” warnings are emitted when loading a
|
||||
state file for simulation.
|
||||
|
||||
- The read-only status of controls in interface simulation mode does
|
||||
not change when the HW/SW button is clicked.
|
||||
|
||||
- When there’s more than one main window open, closing one of them
|
||||
doesn’t free and close everything related to that card.
|
||||
|
||||
- There is no facility to group channels into stereo pairs (needs
|
||||
kernel support to save this information in the interface).
|
||||
|
||||
- There is no facility to give channels custom names (needs kernel
|
||||
support to save this information in the interface).
|
||||
|
||||
- No keyboard accelerators (e.g. Ctrl-Q to quit) have been
|
||||
implemented.
|
||||
@@ -1,33 +1,29 @@
|
||||
Summary: ALSA Scarlett Gen 2/3 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 Scarlett Gen 2/3 Mixer Driver.
|
||||
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
|
||||
cp *.md $DOCDIR
|
||||
cp img/* $DOCDIR/img
|
||||
cp demo/* $DOCDIR/demo
|
||||
%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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
PREFIX=/usr dh $@ --sourcedirectory=src/
|
||||
|
||||
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
5449
demo/Scarlett Gen 1 18i20.state
Normal file
3362
demo/Scarlett Gen 1 18i6.state
Normal file
4165
demo/Scarlett Gen 1 18i8.state
Normal file
3277
demo/Scarlett Gen 1 6i6.state
Normal file
2797
demo/Scarlett Gen 1 8i6.state
Normal file
10648
demo/Scarlett Gen 4 16i16.state
Normal file
11560
demo/Scarlett Gen 4 18i16.state
Normal file
14810
demo/Scarlett Gen 4 18i20.state
Normal file
997
demo/Scarlett Gen 4 2i2.state
Normal file
@@ -0,0 +1,997 @@
|
||||
state.Gen {
|
||||
control.1 {
|
||||
iface PCM
|
||||
name 'Playback Channel Map'
|
||||
value.0 0
|
||||
value.1 0
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 2
|
||||
range '0 - 36'
|
||||
}
|
||||
}
|
||||
control.2 {
|
||||
iface PCM
|
||||
name 'Capture Channel Map'
|
||||
value.0 0
|
||||
value.1 0
|
||||
value.2 0
|
||||
value.3 0
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 4
|
||||
range '0 - 36'
|
||||
}
|
||||
}
|
||||
control.3 {
|
||||
iface CARD
|
||||
name 'USB Internal Validity'
|
||||
value true
|
||||
comment {
|
||||
access read
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.4 {
|
||||
iface CARD
|
||||
name 'Firmware Version'
|
||||
value 2115
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 0'
|
||||
}
|
||||
}
|
||||
control.5 {
|
||||
iface CARD
|
||||
name 'Minimum Firmware Version'
|
||||
value 2115
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 0'
|
||||
}
|
||||
}
|
||||
control.6 {
|
||||
iface MIXER
|
||||
name 'MSD Mode Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.7 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Level Capture Enum'
|
||||
value Line
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Line
|
||||
item.1 Inst
|
||||
}
|
||||
}
|
||||
control.8 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Level Capture Enum'
|
||||
value Line
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Line
|
||||
item.1 Inst
|
||||
}
|
||||
}
|
||||
control.9 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Air Capture Enum'
|
||||
value Off
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 Presence
|
||||
item.2 'Presence + Drive'
|
||||
}
|
||||
}
|
||||
control.10 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Air Capture Enum'
|
||||
value Off
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 Presence
|
||||
item.2 'Presence + Drive'
|
||||
}
|
||||
}
|
||||
control.11 {
|
||||
iface MIXER
|
||||
name 'Line In 1-2 Phantom Power Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.12 {
|
||||
iface MIXER
|
||||
name 'Input Select Capture Enum'
|
||||
value 'Input 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 'Input 1'
|
||||
item.1 'Input 2'
|
||||
}
|
||||
}
|
||||
control.13 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Gain Capture Volume'
|
||||
value 9
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 70 (step 1)'
|
||||
dbmin -7000
|
||||
dbmax 0
|
||||
dbvalue.0 -6100
|
||||
}
|
||||
}
|
||||
control.14 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Autogain Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.15 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Autogain Status Capture Enum'
|
||||
value Stopped
|
||||
comment {
|
||||
access read
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Stopped
|
||||
item.1 Running
|
||||
item.2 Failed
|
||||
item.3 Cancelled
|
||||
item.4 Unknown
|
||||
}
|
||||
}
|
||||
control.16 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Safe Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.17 {
|
||||
iface MIXER
|
||||
name 'Line In 1-2 Link Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.18 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Gain Capture Volume'
|
||||
value 9
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 70 (step 1)'
|
||||
dbmin -7000
|
||||
dbmax 0
|
||||
dbvalue.0 -6100
|
||||
}
|
||||
}
|
||||
control.19 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Autogain Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.20 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Autogain Status Capture Enum'
|
||||
value Stopped
|
||||
comment {
|
||||
access read
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Stopped
|
||||
item.1 Running
|
||||
item.2 Failed
|
||||
item.3 Cancelled
|
||||
item.4 Unknown
|
||||
}
|
||||
}
|
||||
control.21 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Safe Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.22 {
|
||||
iface MIXER
|
||||
name 'Analogue Output 01 Playback Enum'
|
||||
value 'Mix A'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.23 {
|
||||
iface MIXER
|
||||
name 'Analogue Output 02 Playback Enum'
|
||||
value 'Mix B'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.24 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 01 Capture Enum'
|
||||
value 'PCM 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.25 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 02 Capture Enum'
|
||||
value 'PCM 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.26 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 03 Capture Enum'
|
||||
value 'DSP 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.27 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 04 Capture Enum'
|
||||
value 'DSP 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.28 {
|
||||
iface MIXER
|
||||
name 'DSP Input 1 Capture Enum'
|
||||
value 'Analogue 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.29 {
|
||||
iface MIXER
|
||||
name 'DSP Input 2 Capture Enum'
|
||||
value 'Analogue 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.30 {
|
||||
iface MIXER
|
||||
name 'PCM 01 Capture Enum'
|
||||
value 'DSP 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.31 {
|
||||
iface MIXER
|
||||
name 'PCM 02 Capture Enum'
|
||||
value 'DSP 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.32 {
|
||||
iface MIXER
|
||||
name 'PCM 03 Capture Enum'
|
||||
value 'Mix C'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.33 {
|
||||
iface MIXER
|
||||
name 'PCM 04 Capture Enum'
|
||||
value 'Mix D'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'DSP 1'
|
||||
item.8 'DSP 2'
|
||||
item.9 'PCM 1'
|
||||
item.10 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.34 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 01 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.35 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.36 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.37 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.38 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.39 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 02 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.40 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.41 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.42 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 01 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.43 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.44 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.45 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.46 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.47 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 02 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.48 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.49 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.50 {
|
||||
iface PCM
|
||||
name 'Level Meter'
|
||||
value.0 0
|
||||
value.1 0
|
||||
value.2 0
|
||||
value.3 0
|
||||
value.4 0
|
||||
value.5 0
|
||||
value.6 0
|
||||
value.7 0
|
||||
value.8 0
|
||||
value.9 0
|
||||
value.10 0
|
||||
value.11 0
|
||||
comment {
|
||||
access 'read volatile'
|
||||
type INTEGER
|
||||
count 12
|
||||
range '0 - 4095 (step 1)'
|
||||
}
|
||||
}
|
||||
control.51 {
|
||||
iface MIXER
|
||||
name 'Sync Status'
|
||||
value Locked
|
||||
comment {
|
||||
access read
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Unlocked
|
||||
item.1 Locked
|
||||
}
|
||||
}
|
||||
control.52 {
|
||||
iface MIXER
|
||||
name 'Direct Monitor Playback Enum'
|
||||
value Off
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 Mono
|
||||
item.2 Stereo
|
||||
}
|
||||
}
|
||||
control.53 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix A Input 01 Playback Volume'
|
||||
value 150
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -500
|
||||
}
|
||||
}
|
||||
control.54 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix A Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.55 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix A Input 03 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.56 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix A Input 04 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.57 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix B Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.58 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix B Input 02 Playback Volume'
|
||||
value 150
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -500
|
||||
}
|
||||
}
|
||||
control.59 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix B Input 03 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.60 {
|
||||
iface MIXER
|
||||
name 'Monitor 1 Mix B Input 04 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.61 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix A Input 01 Playback Volume'
|
||||
value 150
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -500
|
||||
}
|
||||
}
|
||||
control.62 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix A Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.63 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix A Input 03 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.64 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix A Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.65 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix B Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.66 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix B Input 02 Playback Volume'
|
||||
value 150
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -500
|
||||
}
|
||||
}
|
||||
control.67 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix B Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.68 {
|
||||
iface MIXER
|
||||
name 'Monitor 2 Mix B Input 04 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
}
|
||||
3768
demo/Scarlett Gen 4 4i4.state
Normal file
885
demo/Scarlett Gen 4 Solo.state
Normal file
@@ -0,0 +1,885 @@
|
||||
state.Gen {
|
||||
control.1 {
|
||||
iface PCM
|
||||
name 'Playback Channel Map'
|
||||
value.0 0
|
||||
value.1 0
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 2
|
||||
range '0 - 36'
|
||||
}
|
||||
}
|
||||
control.2 {
|
||||
iface PCM
|
||||
name 'Capture Channel Map'
|
||||
value.0 0
|
||||
value.1 0
|
||||
value.2 0
|
||||
value.3 0
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 4
|
||||
range '0 - 36'
|
||||
}
|
||||
}
|
||||
control.3 {
|
||||
iface CARD
|
||||
name 'USB Internal Validity'
|
||||
value true
|
||||
comment {
|
||||
access read
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.4 {
|
||||
iface CARD
|
||||
name 'Firmware Version'
|
||||
value 2115
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 0'
|
||||
}
|
||||
}
|
||||
control.5 {
|
||||
iface CARD
|
||||
name 'Minimum Firmware Version'
|
||||
value 2115
|
||||
comment {
|
||||
access read
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 0'
|
||||
}
|
||||
}
|
||||
control.6 {
|
||||
iface MIXER
|
||||
name 'MSD Mode Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.7 {
|
||||
iface MIXER
|
||||
name 'Line In 1 Level Capture Enum'
|
||||
value Line
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Line
|
||||
item.1 Inst
|
||||
}
|
||||
}
|
||||
control.8 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Air Capture Enum'
|
||||
value Off
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 Presence
|
||||
item.2 'Presence + Drive'
|
||||
}
|
||||
}
|
||||
control.9 {
|
||||
iface MIXER
|
||||
name 'Line In 2 Phantom Power Capture Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.10 {
|
||||
iface MIXER
|
||||
name 'PCM Input Capture Switch'
|
||||
value Direct
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Direct
|
||||
item.1 Mixer
|
||||
}
|
||||
}
|
||||
control.11 {
|
||||
iface MIXER
|
||||
name 'Analogue Output 01 Playback Enum'
|
||||
value 'Mix A'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.12 {
|
||||
iface MIXER
|
||||
name 'Analogue Output 02 Playback Enum'
|
||||
value 'Mix B'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.13 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 01 Capture Enum'
|
||||
value 'PCM 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.14 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 02 Capture Enum'
|
||||
value 'PCM 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.15 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 03 Capture Enum'
|
||||
value 'DSP 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.16 {
|
||||
iface MIXER
|
||||
name 'Mixer Input 04 Capture Enum'
|
||||
value 'DSP 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.17 {
|
||||
iface MIXER
|
||||
name 'DSP Input 1 Capture Enum'
|
||||
value 'Analogue 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.18 {
|
||||
iface MIXER
|
||||
name 'DSP Input 2 Capture Enum'
|
||||
value 'Analogue 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.19 {
|
||||
iface MIXER
|
||||
name 'PCM 01 Capture Enum'
|
||||
value 'DSP 1'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.20 {
|
||||
iface MIXER
|
||||
name 'PCM 02 Capture Enum'
|
||||
value 'DSP 2'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.21 {
|
||||
iface MIXER
|
||||
name 'PCM 03 Capture Enum'
|
||||
value 'Mix C'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.22 {
|
||||
iface MIXER
|
||||
name 'PCM 04 Capture Enum'
|
||||
value 'Mix D'
|
||||
comment {
|
||||
access 'read write'
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Off
|
||||
item.1 'Analogue 1'
|
||||
item.2 'Analogue 2'
|
||||
item.3 'Mix A'
|
||||
item.4 'Mix B'
|
||||
item.5 'Mix C'
|
||||
item.6 'Mix D'
|
||||
item.7 'Mix E'
|
||||
item.8 'Mix F'
|
||||
item.9 'DSP 1'
|
||||
item.10 'DSP 2'
|
||||
item.11 'PCM 1'
|
||||
item.12 'PCM 2'
|
||||
}
|
||||
}
|
||||
control.23 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 01 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.24 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.25 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.26 {
|
||||
iface MIXER
|
||||
name 'Mix A Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.27 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.28 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 02 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.29 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.30 {
|
||||
iface MIXER
|
||||
name 'Mix B Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.31 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 01 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.32 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.33 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.34 {
|
||||
iface MIXER
|
||||
name 'Mix C Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.35 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.36 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 02 Playback Volume'
|
||||
value 160
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 0
|
||||
}
|
||||
}
|
||||
control.37 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 03 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.38 {
|
||||
iface MIXER
|
||||
name 'Mix D Input 04 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.39 {
|
||||
iface MIXER
|
||||
name 'Mix E Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.40 {
|
||||
iface MIXER
|
||||
name 'Mix E Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.41 {
|
||||
iface MIXER
|
||||
name 'Mix E Input 03 Playback Volume'
|
||||
value 144
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -800
|
||||
}
|
||||
}
|
||||
control.42 {
|
||||
iface MIXER
|
||||
name 'Mix E Input 04 Playback Volume'
|
||||
value 144
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -800
|
||||
}
|
||||
}
|
||||
control.43 {
|
||||
iface MIXER
|
||||
name 'Mix F Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.44 {
|
||||
iface MIXER
|
||||
name 'Mix F Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.45 {
|
||||
iface MIXER
|
||||
name 'Mix F Input 03 Playback Volume'
|
||||
value 144
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -800
|
||||
}
|
||||
}
|
||||
control.46 {
|
||||
iface MIXER
|
||||
name 'Mix F Input 04 Playback Volume'
|
||||
value 144
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -800
|
||||
}
|
||||
}
|
||||
control.47 {
|
||||
iface PCM
|
||||
name 'Level Meter'
|
||||
value.0 0
|
||||
value.1 0
|
||||
value.2 0
|
||||
value.3 0
|
||||
value.4 0
|
||||
value.5 3
|
||||
value.6 0
|
||||
value.7 3
|
||||
value.8 0
|
||||
value.9 3
|
||||
value.10 0
|
||||
value.11 0
|
||||
comment {
|
||||
access 'read volatile'
|
||||
type INTEGER
|
||||
count 12
|
||||
range '0 - 4095 (step 1)'
|
||||
}
|
||||
}
|
||||
control.48 {
|
||||
iface MIXER
|
||||
name 'Sync Status'
|
||||
value Locked
|
||||
comment {
|
||||
access read
|
||||
type ENUMERATED
|
||||
count 1
|
||||
item.0 Unlocked
|
||||
item.1 Locked
|
||||
}
|
||||
}
|
||||
control.49 {
|
||||
iface MIXER
|
||||
name 'Direct Monitor Playback Switch'
|
||||
value false
|
||||
comment {
|
||||
access 'read write'
|
||||
type BOOLEAN
|
||||
count 1
|
||||
}
|
||||
}
|
||||
control.50 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix A Input 01 Playback Volume'
|
||||
value 150
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -500
|
||||
}
|
||||
}
|
||||
control.51 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix A Input 02 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.52 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix A Input 03 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.53 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix A Input 04 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.54 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix B Input 01 Playback Volume'
|
||||
value 0
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -8000
|
||||
}
|
||||
}
|
||||
control.55 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix B Input 02 Playback Volume'
|
||||
value 150
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -500
|
||||
}
|
||||
}
|
||||
control.56 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix B Input 03 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
control.57 {
|
||||
iface MIXER
|
||||
name 'Monitor Mix B Input 04 Playback Volume'
|
||||
value 154
|
||||
comment {
|
||||
access 'read write'
|
||||
type INTEGER
|
||||
count 1
|
||||
range '0 - 172 (step 1)'
|
||||
dbmin -8000
|
||||
dbmax 600
|
||||
dbvalue.0 -300
|
||||
}
|
||||
}
|
||||
}
|
||||
1861
demo/Vocaster One.state
Normal file
3428
demo/Vocaster Two.state
Normal file
188
docs/INSTALL.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# ALSA Scarlett Control Panel Installation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Linux Kernel
|
||||
|
||||
You need to be running a Linux Kernel that contains the appropriate
|
||||
driver for your interface. Use `uname -r` to check what kernel version
|
||||
you are running.
|
||||
|
||||
Check the following table to see which driver your interface uses and
|
||||
the first kernel version that the driver was included in:
|
||||
|
||||
| Series | Models | Driver | Kernel Version |
|
||||
|-----------|--------|--------|:----------------------:|
|
||||
| Scarlett 1st Gen | Solo, 2i2, 2i4 | N/A* | Any |
|
||||
| Scarlett 1st Gen | 6i6, 8i6, 18i6, 18i8, 18i20 | Scarlett 1st Gen Mixer Driver | 3.19+ |
|
||||
| Scarlett 2nd Gen | Solo, 2i2, 2i4 | N/A* | Any |
|
||||
| Scarlett 2nd Gen | 6i6, 18i8, 18i20 | Scarlett2 Mixer Driver | 6.7+ |
|
||||
| Scarlett 3rd Gen | Solo, 2i2, 4i4, 8i6, 18i8, 18i20 | Scarlett2 Mixer Driver | 6.7+ |
|
||||
| Scarlett 4th Gen | Solo, 2i2, 4i4 | Scarlett2 Mixer Driver | 6.8+ |
|
||||
| Scarlett 4th Gen | 16i16, 18i16, 18i20 | FCP (Focusrite Control Protocol) Driver | 6.14+ |
|
||||
| Clarett USB and Clarett+ | 2Pre, 4Pre, 8Pre | Scarlett2 Mixer Driver | 6.7+ |
|
||||
| Vocaster | One, Two | Scarlett2 Mixer Driver | 6.10+ |
|
||||
|
||||
\* The small 1st Gen and 2nd Gen models don’t have any proprietary
|
||||
software controls so they don’t need a driver beyond the standard ALSA
|
||||
USB Audio driver. This means that this application (alsa-scarlett-gui)
|
||||
is not needed, useful, or supported for these models.
|
||||
|
||||
If your distribution doesn’t 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
|
||||
are both maintained in the same tree here):
|
||||
https://github.com/geoffreybennett/linux-fcp/releases
|
||||
|
||||
Kernel 6.7 and later have the Scarlett2 driver enabled by default. The
|
||||
Scarlett 1st Gen driver and the FCP drivers are always enabled.
|
||||
|
||||
#### Enabling the Scarlett2 Driver
|
||||
|
||||
Some kernels before 6.7 have an earlier version of the Scarlett2
|
||||
driver which is disabled by default. If this is you, check the driver
|
||||
status (after plugging your interface in) with this command:
|
||||
|
||||
```
|
||||
dmesg | grep -i -A 5 -B 5 focusrite
|
||||
```
|
||||
|
||||
If all is good you’ll see messages like this:
|
||||
|
||||
```
|
||||
New USB device found, idVendor=1235, idProduct=8215, bcdDevice= 6.0b
|
||||
Product: Scarlett 18i20 USB
|
||||
Focusrite Scarlett Gen 3 Mixer Driver enabled (pid=0x8215); ...
|
||||
```
|
||||
|
||||
If you don’t see the “Mixer Driver” message or if it shows “disabled”
|
||||
then check the [OLDKERNEL.md](OLDKERNEL.md) instructions (or,
|
||||
preferably, upgrade your distro/kernel!).
|
||||
|
||||
### Gtk4
|
||||
|
||||
You need a Linux distribution with Gtk4 development libraries. If it
|
||||
doesn’t have them natively, try the Flatpak instructions below.
|
||||
|
||||
### Firmware
|
||||
|
||||
#### Scarlett2 Driver
|
||||
|
||||
As of Linux 6.8, firmware updates of all supported interfaces from the
|
||||
2nd Gen onwards can be done through Linux. This is mandatory for
|
||||
Scarlett 4th Gen and Vocaster interfaces (unless you’ve already
|
||||
updated it using the manufacturer’s software), and optional but
|
||||
recommended for Scarlett 2nd and 3rd Gen, Clarett USB, and Clarett+
|
||||
interfaces.
|
||||
|
||||
Download the firmware from
|
||||
https://github.com/geoffreybennett/scarlett2-firmware and place it in
|
||||
`/usr/lib/firmware/scarlett2` or use the RPM/deb package.
|
||||
|
||||
#### FCP Driver
|
||||
|
||||
Firmware updates for the big Scarlett 4th Gen interfaces is currently
|
||||
only possible through the CLI `fcp-tool` utility available in the
|
||||
[fcp-support](https://github.com/geoffreybennett/fcp-support). You
|
||||
need to install this package and update the firmware before
|
||||
alsa-scarlett-gui will work.
|
||||
|
||||
## Building and Running
|
||||
|
||||
On Fedora, these packages need to be installed:
|
||||
|
||||
```
|
||||
sudo dnf -y install alsa-lib-devel gtk4-devel openssl-devel
|
||||
```
|
||||
|
||||
On OpenSUSE:
|
||||
|
||||
```
|
||||
sudo zypper in git alsa-devel gtk4-devel libopenssl-devel
|
||||
```
|
||||
|
||||
On Ubuntu:
|
||||
|
||||
```
|
||||
sudo apt -y install git make gcc libgtk-4-dev libasound2-dev libssl-dev
|
||||
```
|
||||
|
||||
On Arch:
|
||||
|
||||
```
|
||||
sudo pacman -S gtk4
|
||||
```
|
||||
|
||||
To download from github:
|
||||
|
||||
```
|
||||
git clone https://github.com/geoffreybennett/alsa-scarlett-gui
|
||||
cd alsa-scarlett-gui
|
||||
```
|
||||
|
||||
To build:
|
||||
|
||||
```
|
||||
cd src
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
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 how to use the GUI.
|
||||
|
||||
## 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 committing!
|
||||
|
||||
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
|
||||
```
|
||||
77
docs/OLDKERNEL.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# ALSA Scarlett2 Usage With Old Kernels
|
||||
|
||||
**This information is mostly for historical purposes. If you’re
|
||||
running a kernel before 6.7, you should upgrade to a newer kernel.**
|
||||
|
||||
Linux kernel 6.7 (check your version with `uname -r`) was the first
|
||||
kernel version with the Scarlett2 driver enabled by default. It’s
|
||||
recommended that you run 6.7 or later, or build the backported driver
|
||||
for your kernel. If you do, then these instructions aren’t relevant;
|
||||
continue with [INSTALL.md](INSTALL.md) for prerequisites, how to
|
||||
build, install, and run `alsa-scarlett-gui`.
|
||||
|
||||
If you’ve got a Scarlett Gen 2 or 3 or a Clarett+ 8Pre and don’t mind
|
||||
the level meters not working, then the first kernel support was 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
|
||||
|
||||
## Linux Kernel with Backported Driver (recommended)
|
||||
|
||||
Install the latest version of the backported driver from here:
|
||||
|
||||
https://github.com/geoffreybennett/linux-fcp/releases
|
||||
|
||||
then you can ignore the instructions below.
|
||||
|
||||
## Linux Kernel before 6.7 without Backported Driver
|
||||
|
||||
If you’re running a kernel before 6.7 without the backported driver,
|
||||
you need to enable it 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 you’ll 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
|
||||
```
|
||||
156
docs/USAGE.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# ALSA Scarlett Control Panel Usage
|
||||
|
||||
Refer to [INSTALL.md](INSTALL.md) for prerequisites, how to build,
|
||||
install, and run.
|
||||
|
||||
## No interface connected
|
||||
|
||||
If no interface is detected (usually because there isn’t one
|
||||
connected!) you’ll see this window:
|
||||
|
||||

|
||||
|
||||
Plug in an interface or select the menu option File → Interface
|
||||
Simulation and load a demo file to make more interesting things
|
||||
happen.
|
||||
|
||||
## First Time Usage
|
||||
|
||||
If your interface is fresh out of the box (or you haven’t updated it
|
||||
using the manufacturer’s software), you may need to update the
|
||||
firmware and/or disable MSD Mode first.
|
||||
|
||||
### Firmware Update Required
|
||||
|
||||
Some interfaces require a firmware update before all their
|
||||
functionality is available. If the firmware is not available on your
|
||||
system, you’ll see this window:
|
||||
|
||||

|
||||
|
||||
In this case, click on the link, download and install the firmware
|
||||
package, then restart `alsa-scarlett-gui`.
|
||||
|
||||
If a firmware update is required and the firmware is available, you’ll
|
||||
see this window:
|
||||
|
||||

|
||||
|
||||
Click “Update”, then “Yes” to update the firmware.
|
||||
|
||||

|
||||
|
||||
The update will take about 15 seconds, and then your interface will
|
||||
restart, showing the main window.
|
||||
|
||||
### MSD (Mass Storage Device/Quick Start/Easy Start) Mode
|
||||
|
||||
If MSD Mode is enabled (as it is from the factory) and a firmware
|
||||
update is not available or required, then you’ll see this window:
|
||||
|
||||

|
||||
|
||||
Click the “Enabled” button to disable MSD Mode, then click “Reboot” to
|
||||
restart the interface, and in a moment the main window will appear.
|
||||
|
||||
## Startup Controls
|
||||
|
||||
The View → Startup menu option opens a window to configure settings
|
||||
that only take effect when the interface is powered on.
|
||||
|
||||
The options common to most interfaces are:
|
||||
|
||||
- **Reset Configuration**: this will reset the configuration to the
|
||||
factory defaults. This is particularly useful with the 4th Gen and
|
||||
Vocaster interfaces if you’ve made a mess of the configuration and
|
||||
want to start again.
|
||||
|
||||
- **Update Firmware**: if a firmware update is found in the
|
||||
`/usr/share/firmware/scarlett2` directory, then an option to update
|
||||
the firmware will be available here.
|
||||
|
||||
## File Menu
|
||||
|
||||
The File menu contains options to load and save the configuration,
|
||||
load a configuration in simulation mode, and to exit the application.
|
||||
|
||||
### Load/Save Configuration
|
||||
|
||||
The entire state of the interface can be loaded and saved using the
|
||||
File → Load Configuration and File → Save Configuration menu options.
|
||||
|
||||
Internally, this uses `alsactl`:
|
||||
|
||||
- **Load**: `alsactl restore USB -f <fn>`
|
||||
- **Save**: `alsactl store USB -f <fn>`
|
||||
|
||||
The saved state files can be used to simulate an interface if you
|
||||
don’t have one attached. The `demo` directory in the distribution
|
||||
contains a sample file for every supported model.
|
||||
|
||||
### Interface Simulation Mode
|
||||
|
||||
The GUI can load an `alsactl` state file saved from a real interface
|
||||
and display a GUI as if the corresponding interface was connected.
|
||||
|
||||
This is useful if you don’t have an interface connected and want to
|
||||
try, develop, or debug the GUI.
|
||||
|
||||
Either specify the `.state` filename on the command line or select the
|
||||
menu option File → Interface Simulation to load.
|
||||
|
||||
## Interface Controls
|
||||
|
||||
The controls and menu items which are available vary widely, depending
|
||||
on your specific interface.
|
||||
|
||||
There are five broad categories of interfaces with different
|
||||
capabilities; each category of interface is described in a separate
|
||||
document:
|
||||
|
||||
- [Scarlett 1st Gen 6i6+](iface-1st-gen.md)
|
||||
|
||||
Full routing and mixing capabilities, but some significant caveats.
|
||||
|
||||
- [Scarlett 3rd Gen Solo and 2i2](iface-small.md)
|
||||
|
||||
Minimal number of controls, and they mostly accessible through
|
||||
hardware buttons anyway. Not very interesting.
|
||||
|
||||
- [Scarlett 2nd Gen 6i6+, 3rd Gen 4i4+, Clarett USB, and
|
||||
Clarett+](iface-large.md)
|
||||
|
||||
Full routing and mixing capabilities.
|
||||
|
||||
- [Scarlett Small 4th Gen](iface-4th-gen-small.md)
|
||||
|
||||
Full routing and mixing capabilities, remote-controlled input gain,
|
||||
but no output controls.
|
||||
|
||||
- [Scarlett Big 4th Gen](iface-4th-gen-big.md)
|
||||
|
||||
Full routing and mixing capabilities, remote-controlled input gain
|
||||
and output volume controls.
|
||||
|
||||
## Known Bugs/Issues
|
||||
|
||||
- For interfaces using the FCP driver, alsa-scarlett-gui needs to be
|
||||
started after the interface is connected and fcp-server has started.
|
||||
|
||||
- Load/Save uses `alsactl` which will be confused if the ALSA
|
||||
interface name (e.g. `USB`) changes.
|
||||
|
||||
- Load/Save is not implemented for simulated interfaces.
|
||||
|
||||
- The read-only status of controls in interface simulation mode does
|
||||
not change when the HW/SW button is clicked.
|
||||
|
||||
- When there’s more than one main window open, closing one of them
|
||||
doesn’t free and close everything related to that card.
|
||||
|
||||
- There is no facility to group channels into stereo pairs (needs
|
||||
kernel support to save this information in the interface).
|
||||
|
||||
- There is no facility to give channels custom names (needs kernel
|
||||
support to save this information in the interface).
|
||||
164
docs/iface-1st-gen.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# ALSA Scarlett Control Panel
|
||||
|
||||
## Scarlett 1st Gen Interfaces
|
||||
|
||||
This document describes how to use the ALSA Scarlett Control Panel
|
||||
with the Scarlett 1st Gen interfaces:
|
||||
|
||||
- Scarlett 1st Gen 6i6, 8i6, 18i6, 18i8, 18i20
|
||||
|
||||
Note: The 1st Gen Scarlett Solo, 2i2, and 2i4 have all their controls
|
||||
accessible from the front panel of the device, and there are no
|
||||
proprietary software controls, so they do not require this control
|
||||
panel software.
|
||||
|
||||
## Important Driver Limitations
|
||||
|
||||
The 1st Gen Scarlett devices have some important limitations in the
|
||||
ALSA driver implementation that you should be aware of:
|
||||
|
||||
1. **Initial State Detection**: The driver cannot read the current
|
||||
state of hardware controls (this appears to be a limitation of the
|
||||
device firmware). When alsa-scarlett-gui starts, what you see will
|
||||
not reflect the actual state of your device unless the controls
|
||||
have previously been set since startup.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
you’ll 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
|
||||
are *not* what you desire.
|
||||
2. Then apply your desired configuration
|
||||
|
||||
This two-step process helps ensure that the driver actually sends all
|
||||
commands to the hardware. You may want to create a script using
|
||||
`alsactl` for this purpose.
|
||||
|
||||
## Main Window
|
||||
|
||||
The main window is divided into three sections:
|
||||
|
||||
- Global Controls
|
||||
- Analogue Input Controls
|
||||
- Analogue Output Controls
|
||||
|
||||
The particular controls available depend on the interface model.
|
||||
|
||||
Note that the View menu option lets you open two other windows which
|
||||
contain additional controls, described in the following sections:
|
||||
- [Routing](#routing)
|
||||
- [Mixer](#mixer)
|
||||
|
||||
The Levels and Startup windows that are available for later-generation
|
||||
interfaces are not available for 1st Gen interfaces due to driver limitations.
|
||||
|
||||
### Global Controls
|
||||
|
||||
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.
|
||||
|
||||
#### 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
|
||||
Unlocked, change the Clock Source to Internal.
|
||||
|
||||
### Analogue Input Controls
|
||||
|
||||
#### Inst
|
||||
|
||||
The Inst buttons are used to select between Mic/Line and Instrument
|
||||
level/impedance. When plugging in microphones or line-level equipment
|
||||
(such as a synthesizer, external preamp, or effects processor) to the
|
||||
input, set it to “Line”. The “Inst” setting is for instruments with
|
||||
pickups such as guitars.
|
||||
|
||||
#### Pad
|
||||
|
||||
Enabling Pad engages a 10dB attenuator in the channel, giving you more
|
||||
headroom for very hot signals.
|
||||
|
||||
#### Gain
|
||||
|
||||
The Gain switch selects Low or High gain for the input channel.
|
||||
|
||||
### Analogue Output Controls
|
||||
|
||||
The analogue output controls let you set the output volume (gain) on
|
||||
the analogue line outputs.
|
||||
|
||||
Click and drag up/down on the volume dial to change the volume, use
|
||||
your arrow keys, Home/End/PgUp/PgDn keys, or use your mouse scroll
|
||||
wheel to adjust. You can also double-click on it to quickly toggle the
|
||||
volume between off and 0dB.
|
||||
|
||||
## Routing
|
||||
|
||||
The routing window allows complete control of signal routing between
|
||||
the hardware inputs/outputs, internal mixer, and PCM (USB)
|
||||
inputs/outputs.
|
||||
|
||||

|
||||
|
||||
To manage the routing connections:
|
||||
|
||||
- Click and drag from a source to a sink or a sink to a source to
|
||||
connect them. Audio from the source will then be sent to that sink.
|
||||
|
||||
- Click on a source or a sink to clear the links connected to that
|
||||
source/sink.
|
||||
|
||||
Note that a sink can only be connected to one source, but one source
|
||||
can be connected to many sinks. If you want a sink to receive input
|
||||
from more than one source, use the mixer inputs and outputs:
|
||||
|
||||
- Connect the sources that you want to mix together to mixer inputs
|
||||
- Connect mixer outputs to the sinks that you want to receive the
|
||||
mixed audio
|
||||
- Use the Mixer window to set the amount of each mixer input that is
|
||||
sent to each mixer output
|
||||
|
||||
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
|
||||
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
|
||||
Outputs.
|
||||
|
||||
- The “Stereo Out” preset connects PCM 1 and 2 Outputs to pairs of
|
||||
Hardware Outputs.
|
||||
|
||||
## Mixer
|
||||
|
||||
If you use the Routing window to connect Sources to Mixer Inputs and
|
||||
Mixer Outputs to Sinks, 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.
|
||||
|
||||
Click and drag up/down on the gain controls to adjust, or use your
|
||||
mouse scroll wheel. You can also double-click on the control to
|
||||
quickly toggle between off and 0dB.
|
||||
210
docs/iface-4th-gen-big.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# ALSA Scarlett Control Panel
|
||||
|
||||
## Scarlett Big 4th Gen Interfaces
|
||||
|
||||
This document describes how to use the ALSA Scarlett Control Panel
|
||||
with the big Scarlett 4th Gen interfaces:
|
||||
|
||||
- Scarlett 4th Gen 16i16, 18i16, 18i20
|
||||
|
||||
### 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
|
||||
installed
|
||||
[fcp-support](https://github.com/geoffreybennett/fcp-support) yet, you
|
||||
need to do that (and update the firmware) before you can use
|
||||
alsa-scarlett-gui.
|
||||
|
||||
## Main Window
|
||||
|
||||
The main window is divided into three sections:
|
||||
- Global Controls
|
||||
- Analogue Input Controls
|
||||
- Analogue Output Controls
|
||||
|
||||
The main window for the 16i16 interface is shown below. The 18i16 and
|
||||
18i20 interfaces are similar, but with more controls.
|
||||
|
||||

|
||||
|
||||
### Global Controls
|
||||
|
||||
#### Clock Source (interfaces with S/PDIF or ADAT inputs only)
|
||||
|
||||
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.
|
||||
|
||||
#### 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 Sync Status
|
||||
is Unlocked, change the Clock Source to Internal.
|
||||
|
||||
#### Sample Rate
|
||||
|
||||
Sample Rate is informative only, and displays the current sample rate
|
||||
if the interface is currently in use. In ALSA, the sample rate is set
|
||||
by the application using the interface, which is usually a sound
|
||||
server such as PulseAudio, JACK, or PipeWire.
|
||||
|
||||
#### Speaker Switching
|
||||
|
||||
Speaker Switching lets you swap between two pairs of monitoring
|
||||
speakers very easily.
|
||||
|
||||
### Analogue Input Controls
|
||||
|
||||
#### Input Select
|
||||
|
||||
The “Input Select” control allows you to choose which channel the
|
||||
hardware 48V, Inst, Air, Auto, and Safe buttons control.
|
||||
|
||||
#### Link
|
||||
|
||||
The “Link” control links the 48V, Inst, Air, Auto, and Safe controls
|
||||
together so that they control a stereo pair of channels
|
||||
simultaneously.
|
||||
|
||||
#### Gain
|
||||
|
||||
The “Gain” controls adjust the input gain for the selected channel.
|
||||
Click and drag up/down on the control to adjust the gain, use your
|
||||
mouse scroll wheel, or click the control to select it and use the
|
||||
arrow keys, Page Up, Page Down, Home, and End keys.
|
||||
|
||||
#### Autogain
|
||||
|
||||
When the “Autogain” control is enabled, the interface will listen to
|
||||
the input signal for ten seconds and automatically adjust the gain to
|
||||
get the best signal level. When autogain is not running, the
|
||||
most-recent autogain exit status is shown below the “Autogain”
|
||||
control.
|
||||
|
||||
#### Safe
|
||||
|
||||
“Safe” mode is a feature that automatically reduces the gain if the
|
||||
signal is too loud. This can be useful to prevent clipping.
|
||||
|
||||
#### Instrument
|
||||
|
||||
The Inst button(s) are used to select between Mic/Line and Instrument
|
||||
level/impedance. When plugging in microphones or line-level equipment
|
||||
(such as a synthesizer, external preamp, or effects processor) to the
|
||||
input, set it to “Line”. The “Inst” setting is for instruments with
|
||||
pickups such as guitars.
|
||||
|
||||
#### Air
|
||||
|
||||
The Scarlett 3rd Gen introduced Air mode which transformed your
|
||||
recordings and inspired you while making music by boosting the
|
||||
signal’s high-end. The 4th Gen interfaces now call that “Air Presence”
|
||||
and add a new mode “Air Presence+Drive” which boosts mid-range
|
||||
harmonics in your sound.
|
||||
|
||||
#### Phantom Power (48V)
|
||||
|
||||
Turning the “48V” switch on sends “Phantom Power” to the XLR
|
||||
microphone input. This is required for some microphones (such as
|
||||
condensor microphones), and damaging to some microphones (particularly
|
||||
vintage ribbon microphones).
|
||||
|
||||
### Analogue Output Controls
|
||||
|
||||
The analogue output controls are a bit sparse. More controls are
|
||||
coming soon.
|
||||
|
||||
#### Volume Knobs
|
||||
|
||||
The volume knobs control the volume of the analogue outputs. The two
|
||||
channels of the stereo pairs are shown separately, but are internally
|
||||
linked together.
|
||||
|
||||
#### Mute and Dim
|
||||
|
||||
The speaker icon buttons are “mute” and “dim” (reduce volume) buttons,
|
||||
corresponding to the front-panel buttons on the interface (although
|
||||
only the 18i20 has a physical dim button).
|
||||
|
||||
## Routing and Mixing
|
||||
|
||||
The routing window allows (almost) complete control of signal routing
|
||||
between the hardware inputs/outputs, internal mixer, and PCM (USB)
|
||||
inputs/outputs.
|
||||
|
||||
The routing and mixing capabilities of the big 4th Gen interfaces are
|
||||
the same in concept as the older interfaces, but the mixer inputs are
|
||||
fixed and not shown in the routing window as there are too many to
|
||||
sensibly display.
|
||||
|
||||
From the main window, open the Routing window with the View → Routing
|
||||
menu option or pressing Ctrl-R:
|
||||
|
||||

|
||||
|
||||
To manage the routing connections:
|
||||
|
||||
- Click and drag from a source to a sink or a sink to a source to
|
||||
connect them. Audio from the source will then be sent to that sink.
|
||||
|
||||
- Click on a source or a sink to clear the links connected to that
|
||||
source/sink.
|
||||
|
||||
Note that a sink can only be connected to one source, but one source
|
||||
can be connected to many sinks. If you want a sink to receive input
|
||||
from more than one source, connect the sinks to mixer outputs:
|
||||
|
||||
- Connect mixer outputs to the sinks that you want to receive the
|
||||
mixed audio
|
||||
- Use the Mixer window to set the amount of each mixer input that is
|
||||
sent to each mixer output
|
||||
|
||||
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
|
||||
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
|
||||
Outputs.
|
||||
|
||||
- The “Stereo Out” preset connects PCM 1 and 2 Outputs to pairs of
|
||||
Hardware Outputs.
|
||||
|
||||
To adjust the routing:
|
||||
|
||||
- Click and drag from a source to a sink or a sink to a source to
|
||||
connect them. Audio from the source will then be sent to that sink.
|
||||
|
||||
- Click on a source or a sink to clear the links connected to that
|
||||
source/sink.
|
||||
|
||||
Note that a sink can only be connected to one source, but one source
|
||||
can be connected to many sinks.
|
||||
|
||||
To adjust the mixer output levels:
|
||||
|
||||
1) Open the mixer window with the main window View → Mixer menu
|
||||
option, or press Ctrl-M.
|
||||
|
||||
2) Mixer levels can be adjusted with your keyboard or mouse in the
|
||||
same way as the [Gain Controls](#gain).
|
||||
|
||||
## Levels
|
||||
|
||||
The meters show the levels seen by the interface at every routing
|
||||
source as well as the analogue outputs. Open this window by selecting
|
||||
the View → Levels menu option or pressing Ctrl-L.
|
||||
|
||||

|
||||
|
||||
Look at this in conjunction with the routing window to understand
|
||||
which meter corresponds to which source or sink.
|
||||
|
||||
Thanks for reading this far! If you appreciate the hundreds of hours
|
||||
of work that went into the kernel driver, the control panel, and this
|
||||
documentation, please consider supporting the author with a
|
||||
[donation](../README.md#donations).
|
||||
346
docs/iface-4th-gen-small.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# ALSA Scarlett Control Panel
|
||||
|
||||
## Scarlett Small 4th Gen Interfaces
|
||||
|
||||
This document describes how to use the ALSA Scarlett Control Panel
|
||||
with the small Scarlett 4th Gen interfaces:
|
||||
|
||||
- Scarlett 4th Gen Solo, 2i2, and 4i4
|
||||
|
||||
### Comparison with earlier Scarlett and Clarett Interfaces
|
||||
|
||||
If you are familiar with the Scarlett 2nd and 3rd Gen interfaces or
|
||||
the Clarett interfaces, the major differences to the 4th Gen
|
||||
interfaces from the point of view of this software are:
|
||||
|
||||
- The 4th Gen Solo and 2i2 interfaces have the full routing and mixing
|
||||
capabilities of the larger 2nd and 3rd Gen and Clarett interfaces
|
||||
(although the line outputs and the headphone outputs are still
|
||||
linked).
|
||||
|
||||
- The 4th Gen 2i2 and 4i4 interfaces have software-controllable
|
||||
(“remote”) input gain controls.
|
||||
|
||||
- The 4th Gen interfaces don’t have the output volume and mute
|
||||
controls that the 2nd and 3rd Gen and Clarett interfaces have.
|
||||
|
||||
- The Air mode with Presence+Drive is implemented with a DSP which is
|
||||
separately routable.
|
||||
|
||||
## Main Window
|
||||
|
||||
The main window is divided into three sections:
|
||||
- Global Controls
|
||||
- Analogue Input Controls
|
||||
- Analogue Output Controls
|
||||
|
||||
The main window for the Solo and 2i2 interfaces is shown below; the
|
||||
4i4 interface is similar to the 2i2, but doesn’t have the Direct
|
||||
Monitor control, and can show the position of the front panel volume
|
||||
knobs.
|
||||
|
||||

|
||||
|
||||
### Global Controls
|
||||
|
||||
#### Sync Status
|
||||
|
||||
Sync Status indicates if the interface is locked to a valid digital
|
||||
clock. This should only ever briefly show “Unlocked” when the sample
|
||||
rate is changed as these interfaces can only use their internal clock.
|
||||
|
||||
#### Power
|
||||
|
||||
The 4i4 has a “Power” control that displays the power status. It can
|
||||
be “Fail”, “Bus”, or “External”. “Fail” means that the interface is
|
||||
not receiving sufficient power; please see the Scarlett 4i4 4th Gen
|
||||
User Guide for more information. “Bus” vs. “External” indicates
|
||||
whether the interface is receiving power from the second USB-C port
|
||||
(“External”) or not (“Bus”).
|
||||
|
||||
#### Sample Rate
|
||||
|
||||
Sample Rate is informative only, and displays the current sample rate
|
||||
if the interface is currently in use. In ALSA, the sample rate is set
|
||||
by the application using the interface, which is usually a sound
|
||||
server such as PulseAudio, JACK, or PipeWire.
|
||||
|
||||
### Analogue Input Controls
|
||||
|
||||
The analogue input controls available depend on the interface model:
|
||||
|
||||
- **Instrument, Air, and Phantom Power**: All models
|
||||
- **Mix**: Solo only (described later in the [Solo Mix
|
||||
Control](#solo-mix-control) section)
|
||||
- **Input Select, Link, Gain, Autogain, and Safe**: 2i2 and 4i4
|
||||
|
||||
#### Instrument
|
||||
|
||||
The Inst button(s) are used to select between Mic/Line and Instrument
|
||||
level/impedance. When plugging in microphones or line-level equipment
|
||||
(such as a synthesizer, external preamp, or effects processor) to the
|
||||
input, set it to “Line”. The “Inst” setting is for instruments with
|
||||
pickups such as guitars.
|
||||
|
||||
#### Air
|
||||
|
||||
The Scarlett 3rd Gen introduced Air mode which transformed your
|
||||
recordings and inspired you while making music by boosting the
|
||||
signal’s high-end. The 4th Gen interfaces now call that “Air Presence”
|
||||
and add a new mode “Air Presence+Drive” which boosts mid-range
|
||||
harmonics in your sound.
|
||||
|
||||
#### Phantom Power (48V)
|
||||
|
||||
Turning the “48V” switch on sends “Phantom Power” to the XLR
|
||||
microphone input. This is required for some microphones (such as
|
||||
condensor microphones), and damaging to some microphones (particularly
|
||||
vintage ribbon microphones).
|
||||
|
||||
The 2i2 has a single 48V switch that controls both channels, and the
|
||||
4i4 has an independent 48V switch for each channel.
|
||||
|
||||
#### Input Select
|
||||
|
||||
The 2i2 and 4i4 interfaces have hardware buttons for 48V, Inst, Air,
|
||||
Auto, and Safe. The “Input Select” control allows you to choose which
|
||||
channel those buttons control.
|
||||
|
||||
#### Link
|
||||
|
||||
The “Link” control links the 48V, Inst, Air, Auto, and Safe controls
|
||||
together so that they control both channels simultaneously.
|
||||
|
||||
#### Gain
|
||||
|
||||
The “Gain” controls adjust the input gain for the selected channel.
|
||||
Click and drag up/down on the control to adjust the gain, use your
|
||||
mouse scroll wheel, or click the control to select it and use the
|
||||
arrow keys, Page Up, Page Down, Home, and End keys.
|
||||
|
||||
#### Autogain
|
||||
|
||||
When the “Autogain” control is enabled, the interface will listen to
|
||||
the input signal for ten seconds and automatically adjust the gain to
|
||||
get the best signal level. When autogain is not running, the
|
||||
most-recent autogain exit status is shown below the “Autogain”
|
||||
control.
|
||||
|
||||
#### Safe
|
||||
|
||||
“Safe” mode is a feature that automatically reduces the gain if the
|
||||
signal is too loud. This can be useful to prevent clipping.
|
||||
|
||||
### Analogue Output Controls
|
||||
|
||||
The analogue output controls available depend on the interface model:
|
||||
|
||||
- **Direct Monitor**: Solo and 2i2
|
||||
- **Volume Knobs**: 4i4
|
||||
|
||||
#### Direct Monitor
|
||||
|
||||
Enabling Direct Monitor sends the analogue input signals to the
|
||||
analogue outputs (speakers/headphones) for zero-latency monitoring.
|
||||
|
||||
On the 2i2, you have the choice of Mono or Stereo monitoring when you
|
||||
click the button:
|
||||
|
||||
- **Mono** sends both inputs to the left and right outputs
|
||||
- **Stereo** sends input 1 to the left, and input 2 to the right
|
||||
output.
|
||||
|
||||
As the 4th Gen Solo and 2i2 interfaces have the full routing and
|
||||
mixing capabilities of the larger 2nd and 3rd Gen interfaces, the
|
||||
Direct Monitor levels can be [adjusted in the
|
||||
mixer](#solo-direct-monitor).
|
||||
|
||||
The 4i4 has no Direct Monitor button, but that functionality can be
|
||||
achieved with [appropriate configuration in the routing and mixing
|
||||
windows](#4i4-sample-direct-monitor-configuration).
|
||||
|
||||
#### Volume Knobs
|
||||
|
||||
The 4i4 interface has volume knobs on the front panel, the position of
|
||||
which is shown in the main window.
|
||||
|
||||
## Routing and Mixing
|
||||
|
||||
The routing and mixing capabilities of the 4th Gen interfaces are the
|
||||
same in concept as the 2nd and 3rd Gen interfaces, but there is a DSP
|
||||
which is separately routable, and the default routing uses the mixer
|
||||
extensively.
|
||||
|
||||
From the main window, open the Routing window with the View → Routing
|
||||
menu option or pressing Ctrl-R:
|
||||
|
||||

|
||||
|
||||
To understand the signal flow, note the following:
|
||||
1. The Analogue 1 & 2 Inputs (i.e. the Mic/Line/Inst inputs) are
|
||||
routed to the DSP Inputs.
|
||||
2. The DSP Outputs are routed to the PCM 1 & 2 Inputs (that’s what
|
||||
ALSA sees as the first two inputs from the interface for
|
||||
recording).
|
||||
3. The PCM Outputs (that’s what ALSA sees as the interface outputs for
|
||||
playback) and the DSP Outputs are all connected to the Mixer
|
||||
Inputs.
|
||||
4. The Mixer A & B Outputs are connected to the Hardware Analogue
|
||||
outputs (i.e. your speakers/headphones) so you can hear any mix of
|
||||
the PCM and DSP Outputs (this is how the Direct Monitor function
|
||||
works).
|
||||
5. The Mixer C & D Outputs are connected to the PCM 3 & 4 Inputs (this
|
||||
is referred to as Loopback, for recording audio from your computer,
|
||||
but can be used for another purpose if you want).
|
||||
|
||||
Important Notes:
|
||||
- The “Presets” are generally not useful with the 4th Gen interfaces
|
||||
as they are designed for the 2nd and 3rd Gen interfaces. If you try
|
||||
these out, you’ll probably want to reset back to the factory
|
||||
defaults afterwards.
|
||||
- Besides Air Mode, the DSP is also used for the gain halo level
|
||||
meters and autogain, so if you route something else to the DSP
|
||||
Inputs, those features will work “rather differently”.
|
||||
- The Focusrite Control 2 software can’t control most of this routing,
|
||||
so if you make changes here and then want to use Focusrite Control
|
||||
2, you’ll probably need to reset the routing back to the factory
|
||||
default settings.
|
||||
|
||||
To adjust the routing:
|
||||
|
||||
- Click and drag from a source to a sink or a sink to a source to
|
||||
connect them. Audio from the source will then be sent to that sink.
|
||||
|
||||
- Click on a source or a sink to clear the links connected to that
|
||||
source/sink.
|
||||
|
||||
Note that a sink can only be connected to one source, but one source
|
||||
can be connected to many sinks.
|
||||
|
||||
To adjust the mixer output levels:
|
||||
|
||||
1) Open the mixer window with the main window View → Mixer menu
|
||||
option, or press Ctrl-M.
|
||||
|
||||
2) Mixer levels can be adjusted with your keyboard or mouse in the
|
||||
same way as the [Gain Controls](#gain).
|
||||
|
||||
### Solo Direct Monitor
|
||||
|
||||
When you enable or disable Direct Monitor on the Solo interface, the
|
||||
interface will update the Mix A and B Outputs so that the DSP 1 & 2
|
||||
Outputs are mixed in (or not) with the PCM 1 & 2 Outputs. Note how the
|
||||
volume of the PCM outputs is also reduced when Direct Monitor is
|
||||
enabled so that you can hear the DSP outputs (i.e. your Analogue
|
||||
inputs) more clearly.
|
||||
|
||||

|
||||
|
||||
If you customise the Mix A/B mixer levels while Direct Monitor is
|
||||
enabled, the new settings will be saved and used when Direct Monitor
|
||||
is enabled again.
|
||||
|
||||
### 2i2 Direct Monitor
|
||||
|
||||
Similarly to the Solo interface, the 2i2 interface will update the Mix
|
||||
A and B Outputs when you enable or disable Direct Monitor, but the 2i2
|
||||
has Mono and Stereo options:
|
||||
|
||||

|
||||
|
||||
Note how in Mono mode:
|
||||
|
||||
- the DSP 1 & 2 Outputs are mixed to both the left and right outputs
|
||||
|
||||
and in Stereo mode:
|
||||
|
||||
- DSP 1 (i.e. Analogue Input 1) is sent to the left output (Mix A),
|
||||
and
|
||||
- DSP 2 (i.e. Analogue Input 2) is sent to the right output (Mix B).
|
||||
|
||||
### Solo Mix Control
|
||||
|
||||
The Mix control is only available on the Solo interface. It switches
|
||||
the source for the PCM 1 & 2 Inputs between the DSP Outputs and the
|
||||
Mixer E & F Outputs.
|
||||
|
||||

|
||||
|
||||
By default, enabling this control will mix the Analogue 1 & 2 Inputs
|
||||
together before they are sent to the PCM 1 & 2 Inputs:
|
||||
|
||||

|
||||
|
||||
This can be useful if you want to treat the PCM 1 & 2 Inputs as a
|
||||
stereo pair, and not have the line/instrument input panned hard left
|
||||
and the microphone input panned hard right.
|
||||
|
||||
The mixer levels for the Mix E & F Outputs can adjusted to suit.
|
||||
|
||||
### 4i4 Routing and Mixing
|
||||
|
||||
Although the 4th Gen 4i4 has no explicit Direct Monitor control, it is
|
||||
far more flexible because it has 6 PCM inputs, 6 PCM outputs, a 10×6
|
||||
mixer, and 6 Analogue Hardware outputs.
|
||||
|
||||
Analogue Outputs 1–4 correspond to the Line Outputs 1–4 on the back of
|
||||
the interface, and Analogue Outputs 5–6 correspond to the Headphone
|
||||
Output on the front of the interface.
|
||||
|
||||
The default routing and mix for the 4i4 is shown below:
|
||||
|
||||

|
||||
|
||||
Note that with the default routing/mix settings:
|
||||
- The Analogue Inputs 1–4 are routed to the PCM Inputs 1–4 (the first
|
||||
two going via the DSP).
|
||||
- PCM Inputs 5–6 are used for Loopback (recording audio from your
|
||||
computer).
|
||||
- All the Hardware Inputs and PCM Outputs are connected to the Mixer
|
||||
Inputs.
|
||||
- PCM Outputs 1–4 are connected to the Analogue Outputs 1–4 (via the
|
||||
mixer).
|
||||
- The Line 1–2 Outputs (Analogue Outputs 1–2) and the Headphones
|
||||
(Analogue Outputs 5–6) share the Mixer Outputs A & B.
|
||||
|
||||
#### 4i4 Sample Direct Monitor Configuration
|
||||
|
||||
A common configuration for the 4i4 is to send the PCM 1 & 2 Outputs
|
||||
mixed with the Analogue Inputs 1 & 2 to the Headphones, while leaving
|
||||
the Analogue Outputs 1–2 as they are. This is an advanced version of
|
||||
the direct monitoring feature that is available on the Solo and 2i2.
|
||||
It can be implemented by:
|
||||
|
||||
1) Route Mixer Outputs E & F to Analogue Outputs 5 & 6.
|
||||
2) Turn up Mix E & F DSP 1 & 2 levels in the mixer (see the mixer
|
||||
example above for [2i2 Direct Monitor](#2i2-direct-monitor)).
|
||||
|
||||
As there are only 6 Mixer Outputs, the PCM 5 & 6 Inputs (Loopback) are
|
||||
now shared with the headphones. If you want to retain the Loopback
|
||||
functionality without having the Analogue Inputs mixed in, you could:
|
||||
- Route the PCM 1 & 2 Outputs directly to the PCM 5 & 6 Inputs, rather
|
||||
than going via the mixer, or
|
||||
- Free up Mixer Outputs A & B for Loopback by routing PCM Outputs 1 &
|
||||
2 directly to Analogue Outputs 1 & 2.
|
||||
|
||||
Besides Direct Monitor, there are many other possibilities for
|
||||
routing/mixing with the 4i4. For example, by using the additional PCM
|
||||
Outputs and Inputs you could set up a mix-minus configuration for a
|
||||
podcast/video call.
|
||||
|
||||
## Levels
|
||||
|
||||
The meters show the levels seen by the interface at every routing
|
||||
sink: Hardware Outputs, Mixer Inputs, DSP Inputs, and PCM Inputs. Open
|
||||
this window by selecting the View → Levels menu option or pressing
|
||||
Ctrl-L.
|
||||
|
||||

|
||||
|
||||
Look at this in conjunction with the routing window to understand
|
||||
which meter corresponds to which source or sink.
|
||||
|
||||
Thanks for reading this far! If you appreciate the hundreds of hours
|
||||
of work that went into the kernel driver, the control panel, and this
|
||||
documentation, please consider supporting the author with a
|
||||
[donation](../README.md#donations).
|
||||
321
docs/iface-large.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# ALSA Scarlett Control Panel
|
||||
|
||||
## Large Scarlett 2nd and 3rd Gen and Clarett Interfaces
|
||||
|
||||
This document describes how to use the ALSA Scarlett Control Panel
|
||||
with the larger Scarlett 2nd Gen, 3rd Gen, and Clarett USB interfaces:
|
||||
|
||||
- Scarlett 2nd Gen 6i6, 18i8, 18i20
|
||||
- Scarlett 3rd Gen 4i4, 8i6, 18i8, 18i20
|
||||
- Clarett 2Pre, 4Pre, 8Pre USB
|
||||
- Clarett+ 2Pre, 4Pre, 8Pre
|
||||
|
||||
## Main Window
|
||||
|
||||
The main window is divided into three sections:
|
||||
|
||||
- Global Controls
|
||||
- Analogue Input Controls
|
||||
- Analogue Output Controls
|
||||
|
||||
The particular controls available depend on the interface model; the
|
||||
3rd Gen 18i20 has all the controls so is shown here:
|
||||
|
||||

|
||||
|
||||
Note that the View menu option lets you open three other windows which
|
||||
contain additional controls, described in the following sections:
|
||||
- [Routing](#routing)
|
||||
- [Mixer](#mixer)
|
||||
- [Levels](#levels)
|
||||
- [Startup](#startup)
|
||||
|
||||
### Global Controls
|
||||
|
||||
Global controls relate to the operation of the interface as a whole.
|
||||
|
||||

|
||||
|
||||
#### Clock Source (interfaces with S/PDIF or ADAT inputs only)
|
||||
|
||||
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.
|
||||
|
||||
#### 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 Sync Status
|
||||
is Unlocked, change the Clock Source to Internal.
|
||||
|
||||
#### Sample Rate
|
||||
|
||||
Sample Rate is informative only, and displays the current sample rate
|
||||
if the interface is currently in use. In ALSA, the sample rate is set
|
||||
by the application using the interface, which is usually a sound
|
||||
server such as PulseAudio, JACK, or PipeWire.
|
||||
|
||||
#### Speaker Switching (Scarlett 3rd Gen 18i8 and 18i20 only)
|
||||
|
||||
Speaker Switching lets you swap between two pairs of monitoring
|
||||
speakers very easily.
|
||||
|
||||
When enabled (Main or Alt):
|
||||
|
||||
- Line Out 1–4 Volume Control Switches are locked to HW
|
||||
- Line Out 3/4 routing is saved
|
||||
- Line Out 3/4 routing is set to the Line Out 1/2 routing
|
||||
|
||||
When set to Main, Line outputs 3 and 4 are muted.
|
||||
|
||||
When set to Alt, Line outputs 1 and 2 are muted.
|
||||
|
||||
When disabled (Off):
|
||||
- Global mute is activated ⭐
|
||||
- Line Out 1–4 Volume Control Switches are unlocked
|
||||
- Line Out 3/4 routing is restored to the saved values
|
||||
|
||||
⭐ You likely won’t expect this to happen. Make sure to unmute the
|
||||
outputs after disabling speaker switching if you want to hear
|
||||
something again.
|
||||
|
||||
#### Talkback (Scarlett 3rd Gen 18i20 only)
|
||||
|
||||
Talkback lets you add another channel (usually the talkback mic) to a
|
||||
mix with a button push, usually to talk to musicians, and without
|
||||
using an additional mic channel.
|
||||
|
||||
The Talkback feature has a few parts:
|
||||
|
||||
- Talkback Microphone connected to Analogue Input 9
|
||||
- Talkback Disable/Enable and Off/On software switches
|
||||
- Talkback Off/On physical switch
|
||||
- Talkback Mix (one switch per mix)
|
||||
- Mix Input 25
|
||||
|
||||
To set up the talkback feature, set Mix Input 25 to the talkback
|
||||
source (usually Analogue Input 9), enable the Talkback Mix switches
|
||||
for the mixes you want the talkback input to be heard on, and change
|
||||
the Talkback control from Disabled to Off. Leave the Mix Input 25 gain
|
||||
controls at zero (−127dB), otherwise the talkback inputs will be heard
|
||||
even when talkback is disabled/off.
|
||||
|
||||
Pressing the Talkback switch on the device will then lower the volume
|
||||
of the other inputs on the mixes for which talkback is enabled and
|
||||
unmute Mix Input 25 on those mixes.
|
||||
|
||||
Talkback can also be activated by changing the Talkback control from
|
||||
Off to On.
|
||||
|
||||
The talkback microphone can also be used just the same as any of the
|
||||
other analogue inputs and routed to a physical output, PCM input, or
|
||||
mixer input.
|
||||
|
||||
### Analogue Input Controls
|
||||
|
||||
This section is applicable to all interfaces except the Scarlett 2nd
|
||||
Gen 18i20 which has hardware-only buttons for these features.
|
||||
|
||||

|
||||
|
||||
#### Inst
|
||||
|
||||
The Inst buttons are used to select between Mic/Line and Instrument
|
||||
level/impedance. When plugging in microphones or line-level equipment
|
||||
(such as a synthesizer, external preamp, or effects processor) to the
|
||||
input, set it to “Line”. The “Inst” setting is for instruments with
|
||||
pickups such as guitars.
|
||||
|
||||
#### Air (Scarlett 3rd Gen and Clarett only)
|
||||
|
||||
Enabling Air will transform your recordings and inspire you while
|
||||
making music.
|
||||
|
||||
#### Pad
|
||||
|
||||
Enabling Pad engages a 10dB attenuator in the channel, giving you more
|
||||
headroom for very hot signals.
|
||||
|
||||
#### Phantom Power (48V)
|
||||
|
||||
Scarlett 2nd Gen and Clarett devices have a hardware button for
|
||||
controlling phantom power.
|
||||
|
||||
Scarlett 3rd Gen devices have hardware and software control of phantom
|
||||
power. Turning the “48V” switch on sends “Phantom Power” to the XLR
|
||||
microphone input. This is required for some microphones (such as
|
||||
condensor microphones), and damaging to some microphones (particularly
|
||||
vintage ribbon microphones).
|
||||
|
||||
On Scarlett 3rd Gen devices, phantom power is turned off by default
|
||||
when the interface is turned on. This can be changed in the startup
|
||||
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 headphone outputs. All interfaces support
|
||||
setting the gain and muting individual channels.
|
||||
|
||||

|
||||
|
||||
Click and drag up/down on the volume dial to change the volume, use
|
||||
your arrow keys, Home/End/PgUp/PgDn keys, or use your mouse scroll
|
||||
wheel to adjust. You can also double-click on it to quickly toggle the
|
||||
volume between off and 0dB.
|
||||
|
||||
The biggest interfaces: Scarlett 2nd Gen 18i20, 3rd Gen 18i8, and 3rd
|
||||
Gen 18i20 have a switchable hardware/software volume control. The
|
||||
position of the big volume knob on the front of the interface is
|
||||
indicated by the “HW” dial in the GUI. The analogue outputs can have
|
||||
their volume set either by the knob (“HW” setting of of the HW/SW
|
||||
button) or by the dials on each output (“SW” setting of the HW/SW
|
||||
button).
|
||||
|
||||
When set to HW, the mute/volume status for those channels is
|
||||
controlled by the hardware volume knob and the global dim/mute
|
||||
controls and the software volume dial and mute button for those
|
||||
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 3rd Gen
|
||||
18i8 doesn’t have physical buttons or indicator lights for these
|
||||
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
|
||||
in addition to the software volume control, therefore both must be
|
||||
turned up in order to hear anything. The other (line 3+) analogue
|
||||
outputs are only controlled by the software controls.
|
||||
|
||||
The volume controls for the headphone outputs on each interface
|
||||
operate in addition to any other hardware or software volume controls
|
||||
for those channels. When using headphones, the volumes for those
|
||||
channels would usually be set to 0dB and the actual volume controlled
|
||||
with the physical headphone volume control(s).
|
||||
|
||||
## Routing
|
||||
|
||||
The routing window allows complete control of signal routing between
|
||||
the hardware inputs/outputs, internal mixer, and PCM (USB)
|
||||
inputs/outputs.
|
||||
|
||||

|
||||
|
||||
To manage the routing connections:
|
||||
|
||||
- Click and drag from a source to a sink or a sink to a source to
|
||||
connect them. Audio from the source will then be sent to that sink.
|
||||
|
||||
- Click on a source or a sink to clear the links connected to that
|
||||
source/sink.
|
||||
|
||||
Note that a sink can only be connected to one source, but one source
|
||||
can be connected to many sinks. If you want a sink to receive input
|
||||
from more than one source, use the mixer inputs and outputs:
|
||||
|
||||
- Connect the sources that you want to mix together to mixer inputs
|
||||
- Connect mixer outputs to the sinks that you want to receive the
|
||||
mixed audio
|
||||
- Use the Mixer window to set the amount of each mixer input that is
|
||||
sent to each mixer output
|
||||
|
||||
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
|
||||
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
|
||||
Outputs.
|
||||
|
||||
- The “Stereo Out” preset connects PCM 1 and 2 Outputs to pairs of
|
||||
Hardware Outputs.
|
||||
|
||||
The Direct routing configuration is the simplest most-generally-useful
|
||||
configuration:
|
||||
|
||||

|
||||
|
||||
### Loopback
|
||||
|
||||
Scarlett 2nd Gen, Clarett USB, and Clarett+ interfaces have as many
|
||||
PCM Inputs as Hardware Inputs. Scarlett 3rd Gen interfaces have two
|
||||
more PCM Inputs which Focusrite Control uses as “Loopback” inputs.
|
||||
|
||||
The “Loopback” feature advertised for Scarlett 3rd Gen devices is
|
||||
actually a limitation of the proprietary Focusrite Control software.
|
||||
All supported devices with a mixer (that’s all but the 2nd and 3rd Gen
|
||||
Solo/2i2 interfaces) support full reassignment of the PCM Inputs, so
|
||||
you can have any PCM Input as a “Loopback” or assigned to any other
|
||||
source.
|
||||
|
||||
### Talkback
|
||||
|
||||
The Scarlett 3rd Gen 18i20 talkback microphone is Analogue Input 9 and
|
||||
can be routed like any other source. If you want to record using it,
|
||||
there is no need for the loopback hack suggested by the manufacturer.
|
||||
Just route it to a PCM Input.
|
||||
|
||||
## Mixer
|
||||
|
||||
If you use the Routing window to connect Sources to Mixer Inputs and
|
||||
Mixer Outputs to Sinks, 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:
|
||||
|
||||

|
||||
|
||||
Click and drag up/down on the gain controls to adjust, or use your
|
||||
mouse scroll wheel. You can also double-click on the control to
|
||||
quickly toggle between off and 0dB.
|
||||
|
||||
## Levels
|
||||
|
||||
The Levels window shows the current levels of the hardware outputs, the
|
||||
mixer inputs, and the PCM inputs.
|
||||
|
||||

|
||||
|
||||
Look at this in conjunction with the routing window to understand
|
||||
which meter corresponds to which source or sink.
|
||||
|
||||
## Startup
|
||||
|
||||
The Startup window is used to configure settings that are
|
||||
applied/relevant when the interface is powered on.
|
||||
|
||||

|
||||
|
||||
### Standalone
|
||||
|
||||
When Standalone mode is enabled, the interface will continue to route
|
||||
audio as per the previous routing and mixer settings after it has been
|
||||
disconnected from a computer. By configuring the routing between the
|
||||
hardware and mixer inputs and outputs appropriately, the interface can
|
||||
act as a standalone preamp or mixer.
|
||||
|
||||
Standalone mode is supported on all devices supported by the kernel
|
||||
driver. Even the Scarlett 3rd Gen 4i4 (which is bus-powered) will
|
||||
operate in standalone mode.
|
||||
|
||||
### Phantom Power Persistence (Scarlett 3rd Gen only)
|
||||
|
||||
When Phantom Power Persistence is enabled, the interface will restore
|
||||
the previous Phantom Power/48V setting when the interface is turned
|
||||
on. For the safety of microphones which can be damaged by phantom
|
||||
power, the interface defaults to having phantom power disabled when it
|
||||
is turned on.
|
||||
|
||||
### Reset Configuration
|
||||
|
||||
This will reset the configuration of the interface to the factory
|
||||
defaults (except for MSD mode which is left off).
|
||||
|
||||
### Update Firmware
|
||||
|
||||
If a firmware update is found in the `/usr/share/firmware/scarlett2`
|
||||
directory, then an option to update the firmware will be available
|
||||
here.
|
||||
56
docs/iface-small.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# ALSA Scarlett Control Panel
|
||||
|
||||
## Small Scarlett 3rd Gen Interfaces
|
||||
|
||||
The Scarlett 3rd Gen Solo and 2i2 interfaces have just a few buttons to control
|
||||
the Air, Line, Phantom Power, and Direct Monitor settings. Mostly
|
||||
nothing that you can’t access from the front panel anyway.
|
||||
|
||||

|
||||
|
||||
## Input Controls
|
||||
|
||||
### Air
|
||||
|
||||
Enabling Air will transform your recordings and inspire you while
|
||||
making music.
|
||||
|
||||
### Inst
|
||||
|
||||
The Inst buttons are used to select between Mic/Line and Instrument
|
||||
level/impedance. When plugging in microphones or line-level equipment
|
||||
(such as a synthesizer, external preamp, or effects processor) to the
|
||||
input, set it to “Line”. The “Inst” setting is for instruments with
|
||||
pickups such as guitars.
|
||||
|
||||
### 48V (Phantom Power)
|
||||
|
||||
Turning the “48V” switch on sends “Phantom Power” to the XLR
|
||||
microphone input(s). This is required for some microphones (such as
|
||||
condensor microphones), and damaging to some microphones (particularly
|
||||
vintage ribbon microphones).
|
||||
|
||||
## Output Controls
|
||||
|
||||
### Direct Monitor
|
||||
|
||||
Direct Monitor sends the analogue input signals to the analogue
|
||||
outputs for zero-latency monitoring.
|
||||
|
||||
On the 2i2, you have the choice of Mono or Stereo monitoring when you
|
||||
click the button. Mono sends both inputs to the left and right
|
||||
outputs. Stereo sends input 1 to the left, and input 2 to the right
|
||||
output.
|
||||
|
||||
## Startup Controls
|
||||
|
||||
#### Phantom Power Persistence
|
||||
|
||||
By default, phantom power is turned off when the interface is turned
|
||||
on. This can be changed in the startup configuration (menu option View
|
||||
→ Startup).
|
||||
|
||||
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.
|
||||
|
||||
BIN
img/alsa-scarlett-gui.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
img/demo.gif
|
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 1.1 MiB |
BIN
img/firmware-missing.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
img/firmware-update-required.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
img/firmware-updating.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
img/iface-4th-gen-big.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
img/iface-4th-gen-small.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
BIN
img/main-global.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
img/main-inputs.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
img/main-outputs.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 51 KiB |
BIN
img/scarlett-1st-gen-6i6-routing.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
img/scarlett-4th-gen-16i16-routing.png
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
img/scarlett-4th-gen-2i2-monitor.gif
Normal file
|
After Width: | Height: | Size: 245 KiB |
BIN
img/scarlett-4th-gen-2i2-routing.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
img/scarlett-4th-gen-4i4-routing.png
Normal file
|
After Width: | Height: | Size: 372 KiB |
BIN
img/scarlett-4th-gen-solo-mix-e-f.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
img/scarlett-4th-gen-solo-mix.gif
Normal file
|
After Width: | Height: | Size: 155 KiB |
BIN
img/scarlett-4th-gen-solo-monitor.gif
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
img/window-levels-3rd-gen.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
img/window-levels-4th-gen-big.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
img/window-levels-4th-gen-small.gif
Normal file
|
After Width: | Height: | Size: 471 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 63 KiB |
11
src/Makefile
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
# SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Credit to Tom Tromey and Paul D. Smith:
|
||||
@@ -12,7 +12,9 @@ VERSION := $(shell \
|
||||
DEPDIR := .deps
|
||||
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
|
||||
|
||||
CFLAGS += -Wall -Werror -ggdb -fno-omit-frame-pointer -O2 -D_FORTIFY_SOURCE=2
|
||||
CFLAGS ?= -ggdb -fno-omit-frame-pointer -fPIE -O2
|
||||
CFLAGS += -Wall -Werror
|
||||
CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3
|
||||
CFLAGS += -DVERSION=\"$(VERSION)\"
|
||||
CFLAGS += -Wno-error=deprecated-declarations
|
||||
|
||||
@@ -25,6 +27,7 @@ CFLAGS += $(shell $(PKG_CONFIG) --cflags alsa)
|
||||
LDFLAGS += $(shell $(PKG_CONFIG) --libs glib-2.0)
|
||||
LDFLAGS += $(shell $(PKG_CONFIG) --libs gtk4)
|
||||
LDFLAGS += $(shell $(PKG_CONFIG) --libs alsa)
|
||||
LDFLAGS += -lm -lcrypto -pie
|
||||
|
||||
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) -c
|
||||
|
||||
@@ -50,7 +53,7 @@ GLIB_COMPILE_RESOURCES := $(shell $(PKG_CONFIG) --variable=glib_compile_resource
|
||||
|
||||
all: $(TARGET) $(DESKTOP_FILE)
|
||||
|
||||
clean:
|
||||
clean: depclean
|
||||
rm -f $(TARGET) $(DESKTOP_FILE) $(OBJS) $(XML_OBJ)
|
||||
|
||||
depclean:
|
||||
@@ -64,7 +67,7 @@ $(DEPFILES):
|
||||
include $(wildcard $(DEPFILES))
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
cc -o $(TARGET) $(OBJS) ${LDFLAGS} -lm
|
||||
$(CC) -o $(TARGET) $(OBJS) ${LDFLAGS}
|
||||
|
||||
ifeq ($(PREFIX),)
|
||||
PREFIX := /usr/local
|
||||
|
||||
21
src/about.c
@@ -1,8 +1,10 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "about.h"
|
||||
|
||||
static GdkTexture *logo = NULL;
|
||||
|
||||
void activate_about(
|
||||
GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
@@ -11,19 +13,26 @@ void activate_about(
|
||||
GtkWindow *w = GTK_WINDOW(data);
|
||||
|
||||
const char *authors[] = {
|
||||
"Geoffrey D. Bennett",
|
||||
"Geoffrey D. Bennett <g@b4.vu>",
|
||||
NULL
|
||||
};
|
||||
|
||||
if (!logo)
|
||||
logo = gdk_texture_new_from_resource(
|
||||
"/vu/b4/alsa-scarlett-gui/icons/vu.b4.alsa-scarlett-gui.png"
|
||||
);
|
||||
|
||||
gtk_show_about_dialog(
|
||||
w,
|
||||
"program-name", "ALSA Scarlett Gen 2/3 Control Panel",
|
||||
"program-name", "ALSA Scarlett Control Panel",
|
||||
"version", "Version " VERSION,
|
||||
"comments", "GTK4 interface to the ALSA Scarlett Gen 2/3 Mixer controls",
|
||||
"comments",
|
||||
"Gtk4 GUI for the ALSA controls presented by the\n"
|
||||
"Linux kernel Focusrite USB drivers",
|
||||
"website", "https://github.com/geoffreybennett/alsa-scarlett-gui",
|
||||
"copyright", "Copyright 2022 Geoffrey D. Bennett",
|
||||
"copyright", "Copyright 2022-2025 Geoffrey D. Bennett",
|
||||
"license-type", GTK_LICENSE_GPL_3_0,
|
||||
"logo-icon-name", "alsa-scarlett-gui-logo",
|
||||
"logo", logo,
|
||||
"title", "About ALSA Scarlett Mixer Interface",
|
||||
"authors", authors,
|
||||
NULL
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/vu/b4/alsa-scarlett-gui/icons">
|
||||
<file alias="alsa-scarlett-gui-logo.png">img/alsa-scarlett-gui-logo.png</file>
|
||||
<file alias="vu.b4.alsa-scarlett-gui.png">img/vu.b4.alsa-scarlett-gui.png</file>
|
||||
<file alias="socket.svg">img/socket.svg</file>
|
||||
<file alias="audio-volume-high.svg">img/audio-volume-high.svg</file>
|
||||
<file alias="audio-volume-low.svg">img/audio-volume-low.svg</file>
|
||||
<file alias="audio-volume-medium.svg">img/audio-volume-medium.svg</file>
|
||||
<file alias="audio-volume-muted.svg">img/audio-volume-muted.svg</file>
|
||||
</gresource>
|
||||
<gresource prefix="/vu/b4/alsa-scarlett-gui">
|
||||
<file>alsa-scarlett-gui.css</file>
|
||||
|
||||
@@ -1,18 +1,373 @@
|
||||
/* Top-level window frame */
|
||||
.window-frame {
|
||||
background: black;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Top-level window content */
|
||||
.window-content {
|
||||
padding: 15px;
|
||||
border: 2px solid #800000;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
/* Title of the window */
|
||||
.window-title {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
.linktext {
|
||||
color: #89CFF0;
|
||||
}
|
||||
|
||||
/* Label above controls-content */
|
||||
.controls-label {
|
||||
font-size: smaller;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
/* controls-content boxes */
|
||||
.controls-content {
|
||||
background: #141414;
|
||||
padding: 10px;
|
||||
border: 1px solid #a00000;
|
||||
border-radius: 5px;
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
/* Tighten up routing groups and make the background a little lighter */
|
||||
.window-routing .controls-content {
|
||||
background: #181818;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/* Used when the controls content is at the top level */
|
||||
.top-level-content {
|
||||
background: #141414;
|
||||
}
|
||||
|
||||
.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-hover {
|
||||
background: #801010;
|
||||
outline: 2px solid #801010;
|
||||
}
|
||||
|
||||
.route-label:drop(active) {
|
||||
box-shadow: none;
|
||||
background: @theme_selected_bg_color;
|
||||
background: #801010;
|
||||
}
|
||||
|
||||
button {
|
||||
.mixer-label {
|
||||
}
|
||||
|
||||
.mixer-label-hover {
|
||||
font-weight: bold;
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
label.gain {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
/* Default button style */
|
||||
.window-frame button {
|
||||
border: 1px solid #303030;
|
||||
background: linear-gradient(175deg, #202020, #282828);
|
||||
box-shadow: none;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.window-frame button.toggle {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.window-frame button:focus:focus-visible {
|
||||
outline: 2px solid #801010;
|
||||
}
|
||||
|
||||
/* padding doesn't work when selected with .window-frame, so use
|
||||
* .toggle instead
|
||||
*/
|
||||
button.toggle {
|
||||
padding: 0px 5px 0px 5px;
|
||||
}
|
||||
|
||||
.window-frame button:checked {
|
||||
color: #ffffff;
|
||||
border: 1px solid #404040;
|
||||
}
|
||||
|
||||
.window-frame button:hover {
|
||||
background: #303030;
|
||||
}
|
||||
|
||||
.window-frame button:disabled {
|
||||
background: #202020;
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
/* Stop text shadows on buttons from being applied to the popup menu */
|
||||
.window-frame button > label > * {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
/* Button controls that are always disabled because they indicate status */
|
||||
.window-frame button.fixed {
|
||||
color: #ffffff;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.window-frame button.fixed label {
|
||||
color: #ffffff;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
/* Combobox controls that are always disabled because they indicate status */
|
||||
.window-frame combobox.fixed > box > button {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Buttons that glow when on */
|
||||
.window-frame button.sync-status {
|
||||
text-shadow: 0 0 5px #a00000, 0 0 15px #800000;
|
||||
}
|
||||
|
||||
.window-frame button.sync-status:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.input-select:checked {
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 5px #00ff00, 0 0 10px #00ff00, 0 0 15px #00ff00;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.window-frame button.input-link:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.autogain:checked {
|
||||
text-shadow: 0 0 5px #0000ff, 0 0 15px #0000ff;
|
||||
}
|
||||
|
||||
.window-frame button.speaker-switching-enable:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.speaker-switching-alt {
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 5px #00ff00, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.speaker-switching-alt:checked {
|
||||
text-shadow: 0 0 5px #ff0000, 0 0 15px #c00000;
|
||||
}
|
||||
|
||||
.window-frame button.talkback-enable:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.talk:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
/* orange */
|
||||
.window-frame .vocaster button.autogain:checked {
|
||||
text-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
|
||||
}
|
||||
|
||||
.window-frame button.safe:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.safe:checked:disabled {
|
||||
text-shadow: 0 0 5px #005000, 0 0 15px #005000;
|
||||
}
|
||||
|
||||
.window-frame button.inst:checked {
|
||||
text-shadow: 0 0 5px #ff0000, 0 0 15px #ff0000;
|
||||
}
|
||||
|
||||
.window-frame .gen4 button.inst:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame .gen4 button.inst:checked:disabled {
|
||||
text-shadow: 0 0 5px #005000, 0 0 15px #005000;
|
||||
}
|
||||
|
||||
.window-frame button.pcm-input-mix:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
/* Air Checked (Gen 3) */
|
||||
.window-frame button.air:checked {
|
||||
text-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
|
||||
}
|
||||
|
||||
/* Air Selections (Gen 4) */
|
||||
.window-frame button.air.selected-presence > label {
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.air.selected-presencedrive > label {
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
|
||||
}
|
||||
|
||||
.window-frame button.air.selected-presence:disabled > label {
|
||||
color: #505050;
|
||||
text-shadow: 0 0 5px #005000, 0 0 15px #005000;
|
||||
}
|
||||
|
||||
.window-frame button.air.selected-presencedrive:disabled > label {
|
||||
color: #505050;
|
||||
text-shadow: 0 0 5px #503c00, 0 0 15px #503c00;
|
||||
}
|
||||
|
||||
.window-frame button.pad:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.gain-switch:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.phantom:checked {
|
||||
text-shadow: 0 0 5px #ff0000, 0 0 15px #c00000;
|
||||
}
|
||||
|
||||
.window-frame .gen4 button.phantom:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame .gen4 button.phantom:checked:disabled {
|
||||
text-shadow: 0 0 5px #005000, 0 0 15px #005000;
|
||||
}
|
||||
|
||||
.window-frame button.input-mute:checked {
|
||||
text-shadow: 0 0 5px #ff0000, 0 0 15px #c00000;
|
||||
}
|
||||
|
||||
.window-frame button.dsp:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
/* Direct Monitor Checked (Solo) */
|
||||
.window-frame .direct-monitor:checked {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
/* Direct Monitor Selections (2i2) */
|
||||
.window-frame button.direct-monitor.selected-mono > label {
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 5px #c0c0c0, 0 0 15px #c0c0c0;
|
||||
}
|
||||
|
||||
.window-frame button.direct-monitor.selected-stereo > label {
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
/* Sample Rates */
|
||||
.window-frame button.sample-rate.sample-rate-44100 {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.sample-rate.sample-rate-48000 {
|
||||
text-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
}
|
||||
|
||||
.window-frame button.sample-rate.sample-rate-88200 {
|
||||
text-shadow: 0 0 5px #ff8000, 0 0 15px #ff8000;
|
||||
}
|
||||
|
||||
.window-frame button.sample-rate.sample-rate-96000 {
|
||||
text-shadow: 0 0 5px #ff8000, 0 0 15px #ff8000;
|
||||
}
|
||||
|
||||
.window-frame button.sample-rate.sample-rate-176400 {
|
||||
text-shadow: 0 0 5px #ff0000, 0 0 15px #c00000;
|
||||
}
|
||||
|
||||
.window-frame button.sample-rate.sample-rate-192000 {
|
||||
text-shadow: 0 0 5px #ff0000, 0 0 15px #c00000;
|
||||
}
|
||||
|
||||
/* Button controls where checked is dimmer */
|
||||
|
||||
/* Mute button */
|
||||
.window-frame button.mute {
|
||||
color: #ffffff;
|
||||
-gtk-icon-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
border-color: #404040;
|
||||
}
|
||||
|
||||
.window-frame button.mute:checked {
|
||||
-gtk-icon-shadow: 0 0 5px #ff0000, 0 0 15px #c00000;
|
||||
border-color: #303030;
|
||||
}
|
||||
|
||||
/* Dim button */
|
||||
.window-frame button.dim {
|
||||
color: #ffffff;
|
||||
-gtk-icon-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
border-color: #404040;
|
||||
}
|
||||
|
||||
.window-frame button.dim:checked {
|
||||
-gtk-icon-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
|
||||
border-color: #303030;
|
||||
}
|
||||
|
||||
/* SW/HW button */
|
||||
.window-frame button.sw-hw {
|
||||
color: #ffffff;
|
||||
-gtk-icon-shadow: 0 0 5px #00c000, 0 0 15px #00c000;
|
||||
border-color: #404040;
|
||||
}
|
||||
|
||||
.window-frame button.sw-hw:checked {
|
||||
color: #808080;
|
||||
-gtk-icon-shadow: 0 0 5px #ffc000, 0 0 15px #ffc000;
|
||||
border-color: #303030;
|
||||
}
|
||||
|
||||
/* Textview used for long descriptions in the startup window */
|
||||
.window-frame textview {
|
||||
color: #ffffff;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.window-frame textview > text {
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* Bigger buttons in the startup window */
|
||||
.window-frame .window-startup button {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/* Separators */
|
||||
.window-frame separator {
|
||||
background: #800000;
|
||||
}
|
||||
|
||||
.window-frame .big-padding {
|
||||
padding: 50px;
|
||||
}
|
||||
|
||||
/* Bigger buttons in confirmation dialogs */
|
||||
.window-frame .big-padding button {
|
||||
padding: 5px 30px;
|
||||
}
|
||||
|
||||
171
src/alsa-sim.c
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "alsa.h"
|
||||
@@ -99,6 +99,53 @@ static void alsa_parse_enum_items(
|
||||
}
|
||||
}
|
||||
|
||||
static void alsa_parse_int_array(
|
||||
snd_config_t *node,
|
||||
long **int_values
|
||||
) {
|
||||
int count = snd_config_is_array(node);
|
||||
if (count < 0) {
|
||||
printf("error: parse int array value %d\n", count);
|
||||
return;
|
||||
}
|
||||
|
||||
*int_values = calloc(count, sizeof(long));
|
||||
|
||||
int item_num = 0;
|
||||
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_for_each(i, next, node) {
|
||||
snd_config_t *node = snd_config_iterator_entry(i);
|
||||
|
||||
const char *key;
|
||||
|
||||
int err = snd_config_get_id(node, &key);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_id error", err);
|
||||
|
||||
int type = snd_config_get_type(node);
|
||||
|
||||
if (type == SND_CONFIG_TYPE_STRING) {
|
||||
const char *string_value;
|
||||
|
||||
err = snd_config_get_string(node, &string_value);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_string error", err);
|
||||
|
||||
if (strcmp(string_value, "true") == 0)
|
||||
(*int_values)[item_num++] = 1;
|
||||
|
||||
} else if (type == SND_CONFIG_TYPE_INTEGER) {
|
||||
long int_value;
|
||||
err = snd_config_get_integer(node, &int_value);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_integer error", err);
|
||||
|
||||
(*int_values)[item_num++] = int_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse a comment node and update elem, e.g.:
|
||||
//
|
||||
// comment {
|
||||
@@ -133,7 +180,7 @@ static void alsa_parse_comment_node(
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_string error", err);
|
||||
if (strstr(access, "write"))
|
||||
elem->writable = 1;
|
||||
elem->is_writable = 1;
|
||||
} else if (strcmp(key, "type") == 0) {
|
||||
if (type != SND_CONFIG_TYPE_STRING) {
|
||||
printf("type type not string\n");
|
||||
@@ -149,15 +196,59 @@ static void alsa_parse_comment_node(
|
||||
elem->type = SND_CTL_ELEM_TYPE_ENUMERATED;
|
||||
else if (strcmp(type, "INTEGER") == 0)
|
||||
elem->type = SND_CTL_ELEM_TYPE_INTEGER;
|
||||
} else if (strcmp(key, "count") == 0) {
|
||||
long count;
|
||||
|
||||
err = snd_config_get_integer(node, &count);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_integer error", err);
|
||||
|
||||
elem->count = count;
|
||||
} else if (strcmp(key, "item") == 0) {
|
||||
alsa_parse_enum_items(node, elem);
|
||||
} else if (strcmp(key, "range") == 0) {
|
||||
if (type != SND_CONFIG_TYPE_STRING) {
|
||||
printf("range type not string\n");
|
||||
return;
|
||||
}
|
||||
const char *range;
|
||||
err = snd_config_get_string(node, &range);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_string error", err);
|
||||
|
||||
// Parse the range string and update elem->min_val and elem->max_val
|
||||
int min_val, max_val;
|
||||
if (sscanf(range, "%d - %d", &min_val, &max_val) == 2) {
|
||||
elem->min_val = min_val;
|
||||
elem->max_val = max_val;
|
||||
}
|
||||
} else if (strcmp(key, "dbmin") == 0) {
|
||||
if (type != SND_CONFIG_TYPE_INTEGER) {
|
||||
printf("dbmin type not integer\n");
|
||||
return;
|
||||
}
|
||||
long dbmin;
|
||||
err = snd_config_get_integer(node, &dbmin);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_integer error", err);
|
||||
elem->min_cdB = dbmin;
|
||||
} else if (strcmp(key, "dbmax") == 0) {
|
||||
if (type != SND_CONFIG_TYPE_INTEGER) {
|
||||
printf("dbmax type not integer\n");
|
||||
return;
|
||||
}
|
||||
long dbmax;
|
||||
err = snd_config_get_integer(node, &dbmax);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_integer error", err);
|
||||
elem->max_cdB = dbmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int alsa_config_to_new_elem(
|
||||
snd_config_t *config,
|
||||
struct alsa_elem *elem
|
||||
struct alsa_card *card,
|
||||
snd_config_t *config
|
||||
) {
|
||||
const char *s;
|
||||
int id;
|
||||
@@ -166,8 +257,11 @@ static int alsa_config_to_new_elem(
|
||||
int value_type = -1;
|
||||
char *string_value = NULL;
|
||||
long int_value;
|
||||
long *int_values = NULL;
|
||||
int err;
|
||||
|
||||
struct alsa_elem elem = {};
|
||||
|
||||
err = snd_config_get_id(config, &s);
|
||||
if (err < 0)
|
||||
fatal_alsa_error("snd_config_get_id error", err);
|
||||
@@ -224,11 +318,14 @@ static int alsa_config_to_new_elem(
|
||||
fatal_alsa_error("snd_config_get_string error", err);
|
||||
string_value = strdup(s);
|
||||
} else if (type == SND_CONFIG_TYPE_COMPOUND) {
|
||||
elem->count = snd_config_is_array(node);
|
||||
elem.count = snd_config_is_array(node);
|
||||
|
||||
if (strcmp(name, "Level Meter") == 0) {
|
||||
seen_value = 1;
|
||||
value_type = SND_CONFIG_TYPE_INTEGER;
|
||||
int_value = 0;
|
||||
} else if (elem.count == 2 && strncmp(name, "Master", 6) == 0) {
|
||||
alsa_parse_int_array(node, &int_values);
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
@@ -242,19 +339,24 @@ static int alsa_config_to_new_elem(
|
||||
|
||||
// comment node?
|
||||
} else if (strcmp(key, "comment") == 0) {
|
||||
alsa_parse_comment_node(node, elem);
|
||||
alsa_parse_comment_node(node, &elem);
|
||||
|
||||
// this isn't needed
|
||||
} else if (strcmp(key, "index") == 0) {
|
||||
|
||||
} else {
|
||||
printf("skipping unknown node %s for %d\n", key, id);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
// check iface value; only interested in MIXER and PCM
|
||||
// check iface value; only interested in CARD, MIXER, and PCM
|
||||
if (!iface) {
|
||||
printf("missing iface node in control id %d\n", id);
|
||||
goto fail;
|
||||
}
|
||||
if (strcmp(iface, "MIXER") != 0 &&
|
||||
if (strcmp(iface, "CARD") != 0 &&
|
||||
strcmp(iface, "MIXER") != 0 &&
|
||||
strcmp(iface, "PCM") != 0)
|
||||
goto fail;
|
||||
|
||||
@@ -272,21 +374,21 @@ static int alsa_config_to_new_elem(
|
||||
|
||||
// integer in config
|
||||
if (value_type == SND_CONFIG_TYPE_INTEGER) {
|
||||
elem->value = int_value;
|
||||
elem.value = int_value;
|
||||
|
||||
// string in config
|
||||
} else if (value_type == SND_CONFIG_TYPE_STRING) {
|
||||
|
||||
// translate boolean true/false
|
||||
if (elem->type == SND_CTL_ELEM_TYPE_BOOLEAN) {
|
||||
if (elem.type == SND_CTL_ELEM_TYPE_BOOLEAN) {
|
||||
if (strcmp(string_value, "true") == 0)
|
||||
elem->value = 1;
|
||||
elem.value = 1;
|
||||
|
||||
// translate enum string value to integer
|
||||
} else if (elem->type == SND_CTL_ELEM_TYPE_ENUMERATED) {
|
||||
for (int i = 0; i < elem->item_count; i++) {
|
||||
if (strcmp(string_value, elem->item_names[i]) == 0) {
|
||||
elem->value = i;
|
||||
} else if (elem.type == SND_CTL_ELEM_TYPE_ENUMERATED) {
|
||||
for (int i = 0; i < elem.item_count; i++) {
|
||||
if (strcmp(string_value, elem.item_names[i]) == 0) {
|
||||
elem.value = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -297,11 +399,30 @@ static int alsa_config_to_new_elem(
|
||||
}
|
||||
}
|
||||
|
||||
elem->numid = id;
|
||||
elem->name = name;
|
||||
elem.card = card;
|
||||
elem.numid = id;
|
||||
elem.name = name;
|
||||
|
||||
// duplicate the element for each channel except for the Level Meter
|
||||
int count = elem.count;
|
||||
|
||||
if (strcmp(elem.name, "Level Meter") == 0)
|
||||
count = 1;
|
||||
|
||||
// for each channel, create a new element and add it to the card
|
||||
// incrementing the index each time
|
||||
for (int i = 0; i < count; i++, elem.index++) {
|
||||
if (count > 1)
|
||||
elem.value = int_values[i];
|
||||
|
||||
int array_len = card->elems->len;
|
||||
g_array_set_size(card->elems, array_len + 1);
|
||||
g_array_index(card->elems, struct alsa_elem, array_len) = elem;
|
||||
}
|
||||
|
||||
free(iface);
|
||||
free(string_value);
|
||||
free(int_values);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -309,6 +430,7 @@ fail:
|
||||
free(iface);
|
||||
free(name);
|
||||
free(string_value);
|
||||
free(int_values);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -333,18 +455,8 @@ static void alsa_config_to_new_card(
|
||||
if (snd_config_get_type(config) != SND_CONFIG_TYPE_COMPOUND)
|
||||
continue;
|
||||
|
||||
struct alsa_elem elem = {};
|
||||
elem.card = card;
|
||||
|
||||
// create the element
|
||||
int err = alsa_config_to_new_elem(node, &elem);
|
||||
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
if (card->elems->len <= elem.numid)
|
||||
g_array_set_size(card->elems, elem.numid + 1);
|
||||
g_array_index(card->elems, struct alsa_elem, elem.numid) = elem;
|
||||
alsa_config_to_new_elem(card, node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,5 +508,8 @@ void create_sim_from_file(GtkWindow *w, char *fn) {
|
||||
|
||||
snd_config_delete(config);
|
||||
|
||||
alsa_set_lr_nums(card);
|
||||
alsa_get_routing_controls(card);
|
||||
|
||||
create_card_window(card);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
1000
src/alsa.c
159
src/alsa.h
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -17,27 +17,46 @@ struct alsa_card;
|
||||
|
||||
// typedef for callbacks to update widgets when the alsa element
|
||||
// notifies of a change
|
||||
typedef void (AlsaElemCallback)(struct alsa_elem *);
|
||||
typedef void (AlsaElemCallback)(struct alsa_elem *, void *);
|
||||
|
||||
// port categories for routing_src and routing_snk entries
|
||||
// must match the level meter ordering from the driver
|
||||
enum {
|
||||
// Hardware inputs/outputs
|
||||
PC_HW = 0,
|
||||
|
||||
// Mixer inputs/outputs
|
||||
PC_MIX = 1,
|
||||
|
||||
// PCM inputs/outputs
|
||||
PC_PCM = 2,
|
||||
|
||||
// number of port categories
|
||||
PC_COUNT = 3
|
||||
PC_OFF, // Off (the source when a sink is not connected)
|
||||
PC_HW, // Hardware inputs/outputs
|
||||
PC_MIX, // Mixer inputs/outputs
|
||||
PC_DSP, // DSP inputs/outputs
|
||||
PC_PCM, // PCM inputs/outputs
|
||||
PC_COUNT // number of port categories
|
||||
};
|
||||
|
||||
// names for the port categories
|
||||
extern const char *port_category_names[PC_COUNT];
|
||||
|
||||
// hardware types
|
||||
enum {
|
||||
HW_TYPE_ANALOGUE,
|
||||
HW_TYPE_SPDIF,
|
||||
HW_TYPE_ADAT,
|
||||
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];
|
||||
|
||||
// is a drag active, and whether dragging from a routing source or a
|
||||
// routing sink
|
||||
enum {
|
||||
@@ -56,7 +75,7 @@ struct routing_src {
|
||||
// the enum id of the alsa item
|
||||
int id;
|
||||
|
||||
// PC_MIX, PC_PCM, or PC_HW
|
||||
// PC_OFF, PC_DSP, PC_MIX, PC_PCM, or PC_HW
|
||||
int port_category;
|
||||
|
||||
// 0-based count within port_category
|
||||
@@ -65,6 +84,9 @@ struct routing_src {
|
||||
// the alsa item name
|
||||
char *name;
|
||||
|
||||
// for PC_HW, the hardware type
|
||||
int hw_type;
|
||||
|
||||
// the number (or translated letter; A = 1) in the item name
|
||||
int lr_num;
|
||||
|
||||
@@ -79,8 +101,6 @@ struct routing_src {
|
||||
// entry in alsa_card routing_snks (routing sinks) array for alsa
|
||||
// elements that are routing sinks like Analogue Output 01 Playback
|
||||
// Enum
|
||||
// port_category is set to PC_MIX, PC_PCM, PC_HW
|
||||
// port_num is a count (0-based) within that category
|
||||
struct routing_snk {
|
||||
|
||||
// location within the array
|
||||
@@ -89,17 +109,23 @@ struct routing_snk {
|
||||
// pointer back to the element this entry is associated with
|
||||
struct alsa_elem *elem;
|
||||
|
||||
// PC_MIX, PC_PCM, or PC_HW
|
||||
int port_category;
|
||||
// box widget on the routing page
|
||||
GtkWidget *box_widget;
|
||||
|
||||
// 0-based count within port_category
|
||||
int port_num;
|
||||
// socket widget on the routing page
|
||||
GtkWidget *socket_widget;
|
||||
|
||||
// the mixer label widgets for this sink
|
||||
GtkWidget *mixer_label_top;
|
||||
GtkWidget *mixer_label_bottom;
|
||||
};
|
||||
|
||||
// hold one callback & its data
|
||||
struct alsa_elem_callback {
|
||||
AlsaElemCallback *callback;
|
||||
void *data;
|
||||
};
|
||||
|
||||
// entry in alsa_card elems (ALSA control elements) array
|
||||
struct alsa_elem {
|
||||
|
||||
@@ -111,27 +137,31 @@ struct alsa_elem {
|
||||
const char *name;
|
||||
int type;
|
||||
int count;
|
||||
int index;
|
||||
|
||||
// for the number (or translated letter; A = 1) in the item name
|
||||
// TODO: move this to struct routing_snk?
|
||||
// for gain/volume elements, the value range, dB type, and dB range
|
||||
int min_val;
|
||||
int max_val;
|
||||
int dB_type;
|
||||
int min_cdB;
|
||||
int max_cdB;
|
||||
|
||||
// level meter labels
|
||||
char **meter_labels;
|
||||
|
||||
// for routing sinks
|
||||
int is_routing_snk;
|
||||
int port_category;
|
||||
int port_num;
|
||||
int hw_type;
|
||||
int lr_num;
|
||||
|
||||
// the primary GTK widget and callback function for this ALSA
|
||||
// control element
|
||||
GtkWidget *widget;
|
||||
AlsaElemCallback *widget_callback;
|
||||
|
||||
// text label for volume controls
|
||||
// handle for routing controls
|
||||
// second button for dual controls
|
||||
GtkWidget *widget2;
|
||||
|
||||
// for boolean buttons, the two possible texts
|
||||
// for dual buttons, the four possible texts
|
||||
const char *bool_text[4];
|
||||
// the callback functions for this ALSA control element
|
||||
GList *callbacks;
|
||||
|
||||
// for simulated elements, the current state
|
||||
int writable;
|
||||
int is_writable;
|
||||
int is_volatile;
|
||||
long value;
|
||||
|
||||
// for simulated enumerated elements, the items
|
||||
@@ -142,13 +172,16 @@ struct alsa_elem {
|
||||
struct alsa_card {
|
||||
int num;
|
||||
char *device;
|
||||
uint32_t pid;
|
||||
char *serial;
|
||||
char *name;
|
||||
int driver_type;
|
||||
char *fcp_socket;
|
||||
int best_firmware_version;
|
||||
snd_ctl_t *handle;
|
||||
struct pollfd pfd;
|
||||
int firmware_version;
|
||||
GArray *elems;
|
||||
struct alsa_elem *sample_capture_elem;
|
||||
struct alsa_elem *level_meter_elem;
|
||||
GArray *routing_srcs;
|
||||
GArray *routing_snks;
|
||||
GIOChannel *io_channel;
|
||||
@@ -158,6 +191,7 @@ struct alsa_card {
|
||||
GtkWidget *window_mixer;
|
||||
GtkWidget *window_levels;
|
||||
GtkWidget *window_startup;
|
||||
GtkWidget *window_modal;
|
||||
GtkWidget *window_main_contents;
|
||||
GtkWidget *routing_grid;
|
||||
GtkWidget *routing_lines;
|
||||
@@ -165,12 +199,13 @@ struct alsa_card {
|
||||
GtkWidget *routing_hw_out_grid;
|
||||
GtkWidget *routing_pcm_in_grid;
|
||||
GtkWidget *routing_pcm_out_grid;
|
||||
GtkWidget *routing_dsp_in_grid;
|
||||
GtkWidget *routing_dsp_out_grid;
|
||||
GtkWidget *routing_mixer_in_grid;
|
||||
GtkWidget *routing_mixer_out_grid;
|
||||
GtkWidget *meters[MAX_METERS];
|
||||
guint meter_gsource_timer;
|
||||
int has_speaker_switching;
|
||||
int has_talkback;
|
||||
int has_fixed_mixer_inputs;
|
||||
int routing_out_count[PC_COUNT];
|
||||
int routing_in_count[PC_COUNT];
|
||||
GMenu *routing_src_menu;
|
||||
@@ -181,25 +216,34 @@ struct alsa_card {
|
||||
double drag_x, drag_y;
|
||||
};
|
||||
|
||||
// global array of cards
|
||||
extern GArray *alsa_cards;
|
||||
|
||||
// utility
|
||||
void fatal_alsa_error(const char *msg, int err);
|
||||
|
||||
// locate elements or get information about them
|
||||
struct alsa_elem *get_elem_by_name(GArray *elems, char *name);
|
||||
struct alsa_elem *get_elem_by_prefix(GArray *elems, char *prefix);
|
||||
int get_max_elem_by_name(GArray *elems, char *prefix, char *needle);
|
||||
int is_elem_routing_snk(struct alsa_elem *elem);
|
||||
struct alsa_elem *get_elem_by_name(GArray *elems, const char *name);
|
||||
struct alsa_elem *get_elem_by_prefix(GArray *elems, const char *prefix);
|
||||
struct alsa_elem *get_elem_by_substr(GArray *elems, const char *substr);
|
||||
int get_max_elem_by_name(
|
||||
GArray *elems,
|
||||
const char *prefix,
|
||||
const char *needle
|
||||
);
|
||||
|
||||
// add callback to alsa_elem callback list
|
||||
void alsa_elem_add_callback(
|
||||
struct alsa_elem *elem,
|
||||
AlsaElemCallback *callback,
|
||||
void *data
|
||||
);
|
||||
|
||||
// alsa snd_ctl_elem_*() functions
|
||||
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);
|
||||
int alsa_get_elem_count(struct alsa_elem *elem);
|
||||
int alsa_get_item_count(struct alsa_elem *elem);
|
||||
char *alsa_get_item_name(struct alsa_elem *elem, int i);
|
||||
@@ -207,6 +251,19 @@ char *alsa_get_item_name(struct alsa_elem *elem, int i);
|
||||
// add to alsa_cards array
|
||||
struct alsa_card *card_create(int card_num);
|
||||
|
||||
// scan/rescan for cards
|
||||
void alsa_scan_cards(void);
|
||||
void alsa_inotify_init(void);
|
||||
// parse elements (used by alsa-sim.c)
|
||||
void alsa_set_lr_nums(struct alsa_card *card);
|
||||
void alsa_get_routing_controls(struct alsa_card *card);
|
||||
|
||||
// init
|
||||
void alsa_init(void);
|
||||
|
||||
// register re-open callback
|
||||
typedef void (ReOpenCallback)(void *);
|
||||
void alsa_register_reopen_callback(
|
||||
const char *serial,
|
||||
ReOpenCallback *callback,
|
||||
void *data
|
||||
);
|
||||
void alsa_unregister_reopen_callback(const char *serial);
|
||||
int alsa_has_reopen_callbacks(void);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -7,7 +7,7 @@
|
||||
#define MAX_MIX_OUT 12
|
||||
|
||||
// maximum number of mux inputs
|
||||
#define MAX_MUX_IN 25
|
||||
#define MAX_MUX_IN 42
|
||||
|
||||
// maximum number of meters
|
||||
#define MAX_METERS 65
|
||||
#define MAX_METERS 92
|
||||
|
||||
83
src/db.c
Normal file
@@ -0,0 +1,83 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <math.h>
|
||||
|
||||
static double db_to_linear(double db) {
|
||||
if (db <= SND_CTL_TLV_DB_GAIN_MUTE)
|
||||
return 0.0;
|
||||
return pow(10.0, db / 20.0);
|
||||
}
|
||||
|
||||
static double linear_to_db(double linear) {
|
||||
if (linear <= 0.0)
|
||||
return SND_CTL_TLV_DB_GAIN_MUTE;
|
||||
return 20.0 * log10(linear);
|
||||
}
|
||||
|
||||
int cdb_to_linear_value(
|
||||
int cdb, int min_val, int max_val, int min_cdb, int max_cdb
|
||||
) {
|
||||
if (cdb <= min_cdb)
|
||||
return min_val;
|
||||
if (cdb >= max_cdb)
|
||||
return max_val;
|
||||
|
||||
// Convert centidB to dB
|
||||
double db = (double)cdb / 100.0;
|
||||
double max_db = (double)max_cdb / 100.0;
|
||||
|
||||
// Convert dB relative to max_db to linear scale 0.0-1.0
|
||||
double linear = db_to_linear(db - max_db);
|
||||
|
||||
// Scale to full ALSA range
|
||||
double scaled = linear * (double)max_val;
|
||||
int value = (int)round(scaled);
|
||||
if (value < min_val)
|
||||
return min_val;
|
||||
if (value > max_val)
|
||||
return max_val;
|
||||
return value;
|
||||
}
|
||||
|
||||
int linear_value_to_cdb(
|
||||
int value, int min_val, int max_val, int min_cdb, int max_cdb
|
||||
) {
|
||||
if (value <= min_val)
|
||||
return min_cdb;
|
||||
if (value >= max_val)
|
||||
return max_cdb;
|
||||
|
||||
// Convert to 0.0-1.0 linear scale
|
||||
double linear = (double)value / (double)max_val;
|
||||
double max_db = (double)max_cdb / 100.0;
|
||||
|
||||
// Convert to dB relative to max_db and back to centidB
|
||||
int cdb = (int)round((linear_to_db(linear) + max_db) * 100.0);
|
||||
if (cdb < min_cdb)
|
||||
return min_cdb;
|
||||
if (cdb > max_cdb)
|
||||
return max_cdb;
|
||||
return cdb;
|
||||
}
|
||||
|
||||
double linear_value_to_db(
|
||||
int value, int min_val, int max_val, int min_db, int max_db
|
||||
) {
|
||||
if (value <= min_val)
|
||||
return min_db;
|
||||
if (value >= max_val)
|
||||
return max_db;
|
||||
|
||||
// Convert to 0.0-1.0 linear scale
|
||||
double linear = (double)value / (double)max_val;
|
||||
|
||||
// Convert to dB relative to max_db
|
||||
double db = linear_to_db(linear) + max_db;
|
||||
if (db < min_db)
|
||||
return min_db;
|
||||
if (db > max_db)
|
||||
return max_db;
|
||||
return db;
|
||||
}
|
||||
16
src/db.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
int cdb_to_linear_value(
|
||||
int cdb, int min_val, int max_val, int min_cdb, int max_cdb
|
||||
);
|
||||
|
||||
int linear_value_to_cdb(
|
||||
int value, int min_val, int max_val, int min_cdb, int max_cdb
|
||||
);
|
||||
|
||||
double linear_value_to_db(
|
||||
int value, int min_val, int max_val, int min_db, int max_db
|
||||
);
|
||||
87
src/device-reset-config.c
Normal file
@@ -0,0 +1,87 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "device-reset-config.h"
|
||||
#include "scarlett2.h"
|
||||
#include "scarlett2-ioctls.h"
|
||||
#include "window-modal.h"
|
||||
|
||||
static gpointer update_progress(
|
||||
struct modal_data *modal_data,
|
||||
char *text,
|
||||
int progress
|
||||
) {
|
||||
struct progress_data *progress_data = g_new0(struct progress_data, 1);
|
||||
progress_data->modal_data = modal_data;
|
||||
progress_data->text = text;
|
||||
progress_data->progress = progress;
|
||||
|
||||
g_main_context_invoke(NULL, modal_update_progress, progress_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define fail(msg) { \
|
||||
if (hwdep) \
|
||||
scarlett2_close(hwdep); \
|
||||
return update_progress(modal_data, msg, -1); \
|
||||
}
|
||||
|
||||
#define failsndmsg(msg) g_strdup_printf(msg, snd_strerror(err))
|
||||
|
||||
gpointer reset_config_thread(gpointer user_data) {
|
||||
struct modal_data *modal_data = user_data;
|
||||
|
||||
update_progress(modal_data, g_strdup("Resetting configuration..."), 0);
|
||||
|
||||
snd_hwdep_t *hwdep;
|
||||
|
||||
int err = scarlett2_open_card(modal_data->card->device, &hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to open hwdep interface: %s"));
|
||||
|
||||
err = scarlett2_erase_config(hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to reset configuration: %s"));
|
||||
|
||||
while (1) {
|
||||
g_usleep(50000);
|
||||
|
||||
err = scarlett2_get_erase_progress(hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to get erase progress: %s"));
|
||||
if (err == 255)
|
||||
break;
|
||||
|
||||
update_progress(modal_data, NULL, err);
|
||||
}
|
||||
|
||||
g_main_context_invoke(NULL, modal_start_reboot_progress, modal_data);
|
||||
scarlett2_reboot(hwdep);
|
||||
scarlett2_close(hwdep);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void join_thread(gpointer thread) {
|
||||
g_thread_join(thread);
|
||||
}
|
||||
|
||||
static void reset_config_yes_callback(struct modal_data *modal_data) {
|
||||
GThread *thread = g_thread_new(
|
||||
"reset_config_thread", reset_config_thread, modal_data
|
||||
);
|
||||
g_object_set_data_full(
|
||||
G_OBJECT(modal_data->button_box), "thread", thread, join_thread
|
||||
);
|
||||
}
|
||||
|
||||
void create_reset_config_window(GtkWidget *w, struct alsa_card *card) {
|
||||
create_modal_window(
|
||||
w, card,
|
||||
"Confirm Reset Configuration",
|
||||
"Resetting Configuration",
|
||||
"Are you sure you want to reset the configuration?",
|
||||
reset_config_yes_callback
|
||||
);
|
||||
}
|
||||
9
src/device-reset-config.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "alsa.h"
|
||||
|
||||
void create_reset_config_window(GtkWidget *w, struct alsa_card *card);
|
||||
140
src/device-update-firmware.c
Normal file
@@ -0,0 +1,140 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "device-reset-config.h"
|
||||
#include "scarlett2.h"
|
||||
#include "scarlett2-firmware.h"
|
||||
#include "scarlett2-ioctls.h"
|
||||
#include "window-modal.h"
|
||||
|
||||
static gpointer update_progress(
|
||||
struct modal_data *modal_data,
|
||||
char *text,
|
||||
int progress
|
||||
) {
|
||||
struct progress_data *progress_data = g_new0(struct progress_data, 1);
|
||||
progress_data->modal_data = modal_data;
|
||||
progress_data->text = text;
|
||||
progress_data->progress = progress;
|
||||
|
||||
g_main_context_invoke(NULL, modal_update_progress, progress_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define fail(msg) { \
|
||||
if (hwdep) \
|
||||
scarlett2_close(hwdep); \
|
||||
if (firmware) \
|
||||
scarlett2_free_firmware_file(firmware); \
|
||||
return update_progress(modal_data, msg, -1); \
|
||||
}
|
||||
|
||||
#define failsndmsg(msg) g_strdup_printf(msg, snd_strerror(err))
|
||||
|
||||
gpointer update_firmware_thread(gpointer user_data) {
|
||||
struct modal_data *modal_data = user_data;
|
||||
struct alsa_card *card = modal_data->card;
|
||||
|
||||
int err = 0;
|
||||
snd_hwdep_t *hwdep = NULL;
|
||||
|
||||
// read the firmware file
|
||||
update_progress(modal_data, g_strdup("Checking firmware..."), 0);
|
||||
struct scarlett2_firmware_file *firmware =
|
||||
scarlett2_get_best_firmware(card->pid);
|
||||
|
||||
// if no firmware, fail
|
||||
if (!firmware)
|
||||
fail(failsndmsg("No update firmware found for device: %s"));
|
||||
|
||||
if (firmware->header.usb_pid != card->pid)
|
||||
fail(g_strdup("Firmware file does not match device"));
|
||||
|
||||
update_progress(modal_data, g_strdup("Resetting configuration..."), 0);
|
||||
|
||||
err = scarlett2_open_card(card->device, &hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to open hwdep interface: %s"));
|
||||
|
||||
err = scarlett2_erase_config(hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to reset configuration: %s"));
|
||||
|
||||
while (1) {
|
||||
g_usleep(50000);
|
||||
|
||||
err = scarlett2_get_erase_progress(hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to get erase progress: %s"));
|
||||
if (err == 255)
|
||||
break;
|
||||
|
||||
update_progress(modal_data, NULL, err);
|
||||
}
|
||||
|
||||
update_progress(modal_data, g_strdup("Erasing flash..."), 0);
|
||||
|
||||
err = scarlett2_erase_firmware(hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to erase upgrade firmware: %s"));
|
||||
|
||||
while (1) {
|
||||
g_usleep(50000);
|
||||
|
||||
err = scarlett2_get_erase_progress(hwdep);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to get erase progress: %s"));
|
||||
if (err == 255)
|
||||
break;
|
||||
|
||||
update_progress(modal_data, NULL, err);
|
||||
}
|
||||
|
||||
update_progress(modal_data, g_strdup("Writing firmware..."), 0);
|
||||
|
||||
size_t offset = 0;
|
||||
size_t len = firmware->header.firmware_length;
|
||||
unsigned char *buf = firmware->firmware_data;
|
||||
|
||||
while (offset < len) {
|
||||
err = snd_hwdep_write(hwdep, buf + offset, len - offset);
|
||||
if (err < 0)
|
||||
fail(failsndmsg("Unable to write firmware: %s"));
|
||||
|
||||
offset += err;
|
||||
|
||||
update_progress(modal_data, NULL, (offset * 100) / len);
|
||||
}
|
||||
|
||||
g_main_context_invoke(NULL, modal_start_reboot_progress, modal_data);
|
||||
scarlett2_reboot(hwdep);
|
||||
scarlett2_close(hwdep);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void join_thread(gpointer thread) {
|
||||
g_thread_join(thread);
|
||||
}
|
||||
|
||||
static void update_firmware_yes_callback(struct modal_data *modal_data) {
|
||||
GThread *thread = g_thread_new(
|
||||
"update_firmware_thread", update_firmware_thread, modal_data
|
||||
);
|
||||
g_object_set_data_full(
|
||||
G_OBJECT(modal_data->button_box), "thread", thread, join_thread
|
||||
);
|
||||
}
|
||||
|
||||
void create_update_firmware_window(GtkWidget *w, struct alsa_card *card) {
|
||||
create_modal_window(
|
||||
w, card,
|
||||
"Confirm Update Firmware",
|
||||
"Updating Firmware",
|
||||
"The firmware update process will take about 15 seconds.\n"
|
||||
"Please do not disconnect the device while updating.\n"
|
||||
"Ready to proceed?",
|
||||
update_firmware_yes_callback
|
||||
);
|
||||
}
|
||||
9
src/device-update-firmware.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "alsa.h"
|
||||
|
||||
void create_update_firmware_window(GtkWidget *w, struct alsa_card *card);
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "error.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
19
src/fcp-shared.c
Normal 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
@@ -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
@@ -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
@@ -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);
|
||||
11
src/file.c
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "alsa.h"
|
||||
@@ -14,9 +14,15 @@ static void run_alsactl(
|
||||
) {
|
||||
GtkWindow *w = GTK_WINDOW(card->window_main);
|
||||
|
||||
gchar *alsactl_path = g_find_program_in_path("alsactl");
|
||||
|
||||
if (!alsactl_path)
|
||||
alsactl_path = g_strdup("/usr/sbin/alsactl");
|
||||
|
||||
gchar *argv[] = {
|
||||
"/usr/sbin/alsactl", cmd, card->device, "-f", fn, NULL
|
||||
alsactl_path, cmd, card->device, "-f", fn, NULL
|
||||
};
|
||||
|
||||
gchar *stdout;
|
||||
gchar *stderr;
|
||||
gint exit_status;
|
||||
@@ -52,6 +58,7 @@ static void run_alsactl(
|
||||
g_free(error_message);
|
||||
|
||||
done:
|
||||
g_free(alsactl_path);
|
||||
g_free(stdout);
|
||||
g_free(stderr);
|
||||
if (error)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
2015
src/gtkdial.c
152
src/gtkdial.h
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2021 Stiliyan Varbanov <https://www.fiverr.com/stilvar>
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
/*
|
||||
@@ -14,92 +14,100 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_DIAL (gtk_dial_get_type ())
|
||||
#define GTK_DIAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DIAL, GtkDial))
|
||||
#define GTK_DIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DIAL, GtkDialClass))
|
||||
#define GTK_IS_DIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DIAL))
|
||||
#define GTK_IS_DIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DIAL))
|
||||
#define GTK_DIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DIAL, GtkDialClass))
|
||||
#define GTK_TYPE_DIAL (gtk_dial_get_type())
|
||||
#define GTK_DIAL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_DIAL, GtkDial))
|
||||
#define GTK_DIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_DIAL, GtkDialClass))
|
||||
#define GTK_IS_DIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_DIAL))
|
||||
#define GTK_IS_DIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_DIAL))
|
||||
#define GTK_DIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_DIAL, GtkDialClass))
|
||||
|
||||
typedef struct _GtkDial GtkDial;
|
||||
typedef struct _GtkDialClass GtkDialClass;
|
||||
typedef struct _GtkDial GtkDial;
|
||||
typedef struct _GtkDialClass GtkDialClass;
|
||||
|
||||
struct _GtkDialClass
|
||||
{
|
||||
struct _GtkDialClass {
|
||||
GtkWidgetClass parent_class;
|
||||
|
||||
void (* value_changed) (GtkDial *dial);
|
||||
void (*value_changed)(GtkDial *dial);
|
||||
|
||||
/* action signals for keybindings */
|
||||
void (* move_slider) (GtkDial *dial,
|
||||
GtkScrollType scroll);
|
||||
void (*move_slider)(GtkDial *dial, GtkScrollType scroll);
|
||||
|
||||
gboolean (*change_value) (GtkDial *dial,
|
||||
GtkScrollType scroll,
|
||||
double new_value);
|
||||
gboolean (*change_value)(
|
||||
GtkDial *dial,
|
||||
GtkScrollType scroll,
|
||||
double new_value
|
||||
);
|
||||
};
|
||||
|
||||
typedef char * (*GtkDialFormatValueFunc) (GtkDial *dial,
|
||||
double value,
|
||||
gpointer user_data);
|
||||
GType gtk_dial_get_type(void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_dial_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_dial_new (GtkAdjustment *adjustment);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_dial_new_with_range (double min,
|
||||
double max,
|
||||
double step);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_dial_set_has_origin (GtkDial *dial,
|
||||
gboolean has_origin);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_dial_get_has_origin (GtkDial *dial);
|
||||
GtkWidget *gtk_dial_new(GtkAdjustment *adjustment);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_dial_set_adjustment (GtkDial *dial,
|
||||
GtkAdjustment *adj);
|
||||
GtkWidget *gtk_dial_new_with_range(
|
||||
double min,
|
||||
double max,
|
||||
double step,
|
||||
double page
|
||||
);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial);
|
||||
void gtk_dial_set_has_origin(GtkDial *dial, gboolean has_origin);
|
||||
gboolean gtk_dial_get_has_origin(GtkDial *dial);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double gtk_dial_get_value (GtkDial *dial);
|
||||
void gtk_dial_set_adjustment(GtkDial *dial, GtkAdjustment *adj);
|
||||
GtkAdjustment *gtk_dial_get_adjustment(GtkDial *dial);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_dial_set_value (GtkDial *dial,
|
||||
double value);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_dial_set_round_digits (GtkDial *dial,
|
||||
int round_digits);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gtk_dial_get_round_digits (GtkDial *range);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_dial_set_zero_db (GtkDial *dial,
|
||||
double zero_db);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double gtk_dial_get_zero_db (GtkDial *range);
|
||||
double gtk_dial_get_value(GtkDial *dial);
|
||||
void gtk_dial_set_value(GtkDial *dial, double value);
|
||||
|
||||
void gtk_dial_set_round_digits(GtkDial *dial, int round_digits);
|
||||
int gtk_dial_get_round_digits(GtkDial *dial);
|
||||
|
||||
void gtk_dial_set_zero_db(GtkDial *dial, double zero_db);
|
||||
double gtk_dial_get_zero_db(GtkDial *dial);
|
||||
|
||||
void gtk_dial_set_off_db(GtkDial *dial, double off_db);
|
||||
double gtk_dial_get_off_db(GtkDial *dial);
|
||||
|
||||
void gtk_dial_set_is_linear(GtkDial *dial, gboolean is_linear);
|
||||
gboolean gtk_dial_get_is_linear(GtkDial *dial);
|
||||
|
||||
// taper functions
|
||||
enum {
|
||||
GTK_DIAL_TAPER_LINEAR,
|
||||
GTK_DIAL_TAPER_LOG
|
||||
};
|
||||
|
||||
void gtk_dial_set_taper(GtkDial *dial, int taper);
|
||||
int gtk_dial_get_taper(GtkDial *dial);
|
||||
|
||||
void gtk_dial_set_taper_linear_breakpoints(
|
||||
GtkDial *dial,
|
||||
const double *breakpoints,
|
||||
const double *outputs,
|
||||
int count
|
||||
);
|
||||
|
||||
void gtk_dial_set_can_control(GtkDial *dial, gboolean can_control);
|
||||
gboolean gtk_dial_get_can_control(GtkDial *dial);
|
||||
|
||||
void gtk_dial_set_level_meter_colours(
|
||||
GtkDial *dial,
|
||||
const int *breakpoints,
|
||||
const double *colours,
|
||||
int count
|
||||
);
|
||||
|
||||
void gtk_dial_set_peak_hold(GtkDial *dial, int peak_hold);
|
||||
int gtk_dial_get_peak_hold(GtkDial *dial);
|
||||
void gtk_dial_peak_tick(void);
|
||||
|
||||
int cdb_to_linear_value(
|
||||
int db, int min_val, int max_val, int min_db, int max_db
|
||||
);
|
||||
int linear_value_to_cdb(
|
||||
int value, int min_val, int max_val, int min_db, int max_db
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Set the colors which this dial uses. String codes can be one of the following:
|
||||
* A standard name (Taken from the X11 rgb.txt file)
|
||||
* A hexadecimal value in the form “#rgb”, “#rrggbb”, “#rrrgggbbb” or ”#rrrrggggbbbb”
|
||||
* A RGB color in the form “rgb(r,g,b)” (In this case the color will have full opacity)
|
||||
* A RGBA color in the form “rgba(r,g,b,a)”
|
||||
* NULL if the color is to remain unchanged
|
||||
*
|
||||
* @param dial: The dial
|
||||
* @param trough_border: String code for trough border color
|
||||
* @param trough_bg: String code for trough background color
|
||||
* @param trough_fill: String code for trough fill color
|
||||
* @return TRUE if all the colors were set successfully, FALSE otherwise
|
||||
*/
|
||||
gboolean gtk_dial_set_style(GtkDial *dial,
|
||||
const char *trough_border,
|
||||
const char *trough_bg,
|
||||
const char *trough_fill,
|
||||
const char *pointer);
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "gtkhelper.h"
|
||||
@@ -25,7 +25,15 @@ void gtk_grid_set_spacing(GtkGrid *grid, int spacing) {
|
||||
gtk_grid_set_column_spacing(grid, spacing);
|
||||
}
|
||||
|
||||
void gtk_widget_add_class(GtkWidget *w, const char *class) {
|
||||
GtkStyleContext *style_context = gtk_widget_get_style_context(w);
|
||||
gtk_style_context_add_class(style_context, class);
|
||||
void gtk_widget_remove_css_classes_by_prefix(
|
||||
GtkWidget *w,
|
||||
const char *prefix
|
||||
) {
|
||||
char **classes = gtk_widget_get_css_classes(w);
|
||||
|
||||
for (char **i = classes; *i != NULL; i++)
|
||||
if (strncmp(*i, prefix, strlen(prefix)) == 0)
|
||||
gtk_widget_remove_css_class(w, *i);
|
||||
|
||||
g_strfreev(classes);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -9,4 +9,4 @@ void gtk_widget_set_margin(GtkWidget *w, int margin);
|
||||
void gtk_widget_set_expand(GtkWidget *w, gboolean expand);
|
||||
void gtk_widget_set_align(GtkWidget *w, GtkAlign x, GtkAlign y);
|
||||
void gtk_grid_set_spacing(GtkGrid *grid, int spacing);
|
||||
void gtk_widget_add_class(GtkWidget *w, const char *class);
|
||||
void gtk_widget_remove_css_classes_by_prefix(GtkWidget *w, const char *prefix);
|
||||
|
||||
38
src/hardware.c
Normal file
@@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
struct scarlett2_device scarlett2_supported[] = {
|
||||
{ 0x8203, "Scarlett 2nd Gen 6i6" },
|
||||
{ 0x8204, "Scarlett 2nd Gen 18i8" },
|
||||
{ 0x8201, "Scarlett 2nd Gen 18i20" },
|
||||
{ 0x8211, "Scarlett 3rd Gen Solo" },
|
||||
{ 0x8210, "Scarlett 3rd Gen 2i2" },
|
||||
{ 0x8212, "Scarlett 3rd Gen 4i4" },
|
||||
{ 0x8213, "Scarlett 3rd Gen 8i6" },
|
||||
{ 0x8214, "Scarlett 3rd Gen 18i8" },
|
||||
{ 0x8215, "Scarlett 3rd Gen 18i20" },
|
||||
{ 0x8216, "Vocaster One" },
|
||||
{ 0x8217, "Vocaster Two" },
|
||||
{ 0x8218, "Scarlett 4th Gen Solo" },
|
||||
{ 0x8219, "Scarlett 4th Gen 2i2" },
|
||||
{ 0x821a, "Scarlett 4th Gen 4i4" },
|
||||
{ 0x8206, "Clarett USB 2Pre" },
|
||||
{ 0x8207, "Clarett USB 4Pre" },
|
||||
{ 0x8208, "Clarett USB 8Pre" },
|
||||
{ 0x820a, "Clarett+ 2Pre" },
|
||||
{ 0x820b, "Clarett+ 4Pre" },
|
||||
{ 0x820c, "Clarett+ 8Pre" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct scarlett2_device *get_device_for_pid(int pid) {
|
||||
for (int i = 0; scarlett2_supported[i].name; i++)
|
||||
if (scarlett2_supported[i].pid == pid)
|
||||
return &scarlett2_supported[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
10
src/hardware.h
Normal file
@@ -0,0 +1,10 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// Supported devices
|
||||
struct scarlett2_device {
|
||||
int pid;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct scarlett2_device *get_device_for_pid(int pid);
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-FileCopyrightText: 2022-2025 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "gtkhelper.h"
|
||||
@@ -6,38 +6,49 @@
|
||||
#include "stringhelper.h"
|
||||
#include "tooltips.h"
|
||||
#include "widget-boolean.h"
|
||||
#include "widget-combo.h"
|
||||
#include "widget-drop-down.h"
|
||||
#include "window-helper.h"
|
||||
#include "window-startup.h"
|
||||
|
||||
GtkWidget *create_iface_no_mixer_main(struct alsa_card *card) {
|
||||
GArray *elems = card->elems;
|
||||
|
||||
GtkWidget *grid = gtk_grid_new();
|
||||
GtkWidget *top = gtk_frame_new(NULL);
|
||||
gtk_widget_add_css_class(top, "window-frame");
|
||||
|
||||
GtkWidget *content = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 15);
|
||||
gtk_widget_add_css_class(content, "window-content");
|
||||
gtk_widget_add_css_class(content, "iface-no-mixer");
|
||||
gtk_frame_set_child(GTK_FRAME(top), content);
|
||||
|
||||
GtkWidget *input_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
GtkWidget *output_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_box_append(GTK_BOX(content), input_box);
|
||||
gtk_box_append(GTK_BOX(content), output_box);
|
||||
|
||||
GtkWidget *label_ic = gtk_label_new("Input Controls");
|
||||
GtkWidget *vert_sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
|
||||
GtkWidget *label_oc = gtk_label_new("Output Controls");
|
||||
|
||||
gtk_widget_set_margin(grid, 10);
|
||||
gtk_grid_set_spacing(GTK_GRID(grid), 10);
|
||||
gtk_widget_add_css_class(label_ic, "controls-label");
|
||||
gtk_widget_add_css_class(label_oc, "controls-label");
|
||||
|
||||
gtk_grid_attach(GTK_GRID(grid), label_ic, 0, 0, 1, 1);
|
||||
gtk_grid_attach(GTK_GRID(grid), vert_sep, 1, 0, 1, 3);
|
||||
gtk_grid_attach(GTK_GRID(grid), label_oc, 2, 0, 1, 1);
|
||||
gtk_widget_set_halign(label_ic, GTK_ALIGN_START);
|
||||
gtk_widget_set_halign(label_oc, GTK_ALIGN_START);
|
||||
|
||||
GtkWidget *horiz_input_sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_grid_attach(GTK_GRID(grid), horiz_input_sep, 0, 1, 1, 1);
|
||||
gtk_box_append(GTK_BOX(input_box), label_ic);
|
||||
gtk_box_append(GTK_BOX(output_box), label_oc);
|
||||
|
||||
GtkWidget *input_grid = gtk_grid_new();
|
||||
gtk_grid_set_spacing(GTK_GRID(input_grid), 10);
|
||||
gtk_grid_attach(GTK_GRID(grid), input_grid, 0, 2, 1, 1);
|
||||
|
||||
GtkWidget *horiz_output_sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
|
||||
gtk_grid_attach(GTK_GRID(grid), horiz_output_sep, 2, 1, 1, 1);
|
||||
gtk_widget_add_css_class(input_grid, "controls-content");
|
||||
gtk_widget_set_vexpand(input_grid, TRUE);
|
||||
gtk_box_append(GTK_BOX(input_box), input_grid);
|
||||
|
||||
GtkWidget *output_grid = gtk_grid_new();
|
||||
gtk_grid_set_spacing(GTK_GRID(output_grid), 10);
|
||||
gtk_grid_attach(GTK_GRID(grid), output_grid, 2, 2, 1, 1);
|
||||
gtk_widget_add_css_class(output_grid, "controls-content");
|
||||
gtk_widget_set_vexpand(output_grid, TRUE);
|
||||
gtk_box_append(GTK_BOX(output_box), output_grid);
|
||||
|
||||
// Solo or 2i2?
|
||||
// Solo Phantom Power is Line 1 only
|
||||
@@ -48,7 +59,7 @@ GtkWidget *create_iface_no_mixer_main(struct alsa_card *card) {
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
char s[20];
|
||||
snprintf(s, 20, "Analogue %d", i + 1);
|
||||
snprintf(s, 20, "%d", i + 1);
|
||||
GtkWidget *label = gtk_label_new(s);
|
||||
gtk_grid_attach(GTK_GRID(input_grid), label, i, 0, 1, 1);
|
||||
}
|
||||
@@ -67,23 +78,25 @@ GtkWidget *create_iface_no_mixer_main(struct alsa_card *card) {
|
||||
int line_num = get_num_from_string(elem->name);
|
||||
|
||||
if (strstr(elem->name, "Level Capture Enum")) {
|
||||
w = make_boolean_alsa_elem(elem, "Line", "Inst");
|
||||
w = make_boolean_alsa_elem(elem, "Inst", NULL);
|
||||
gtk_widget_add_css_class(w, "inst");
|
||||
gtk_widget_set_tooltip_text(w, level_descr);
|
||||
gtk_grid_attach(GTK_GRID(input_grid), w, line_num - 1, 1, 1, 1);
|
||||
} else if (strstr(elem->name, "Air Capture Switch")) {
|
||||
w = make_boolean_alsa_elem(elem, "Air Off", "Air On");
|
||||
w = make_boolean_alsa_elem(elem, "Air", NULL);
|
||||
gtk_widget_add_css_class(w, "air");
|
||||
gtk_widget_set_tooltip_text(w, air_descr);
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(input_grid), w, line_num - 1, 1 + !is_solo, 1, 1
|
||||
);
|
||||
} else if (strstr(elem->name, "Phantom Power Capture Switch")) {
|
||||
w = make_boolean_alsa_elem(elem, "48V Off", "48V On");
|
||||
w = make_boolean_alsa_elem(elem, "48V", NULL);
|
||||
gtk_widget_add_css_class(w, "phantom");
|
||||
gtk_widget_set_tooltip_text(w, phantom_descr);
|
||||
gtk_grid_attach(GTK_GRID(input_grid), w, 0, 3, 1 + !is_solo, 1);
|
||||
} else if (strcmp(elem->name, "Direct Monitor Playback Switch") == 0) {
|
||||
w = make_boolean_alsa_elem(
|
||||
elem, "Direct Monitor Off", "Direct Monitor On"
|
||||
);
|
||||
w = make_boolean_alsa_elem(elem, "Direct Monitor", NULL);
|
||||
gtk_widget_add_css_class(w, "direct-monitor");
|
||||
gtk_widget_set_tooltip_text(
|
||||
w,
|
||||
"Direct Monitor sends the analogue input signals to the "
|
||||
@@ -91,9 +104,8 @@ GtkWidget *create_iface_no_mixer_main(struct alsa_card *card) {
|
||||
);
|
||||
gtk_grid_attach(GTK_GRID(output_grid), w, 0, 0, 1, 1);
|
||||
} else if (strcmp(elem->name, "Direct Monitor Playback Enum") == 0) {
|
||||
GtkWidget *l = gtk_label_new("Direct Monitor");
|
||||
gtk_grid_attach(GTK_GRID(output_grid), l, 0, 0, 1, 1);
|
||||
w = make_combo_box_alsa_elem(elem);
|
||||
w = make_drop_down_alsa_elem(elem, "Direct Monitor");
|
||||
gtk_widget_add_css_class(w, "direct-monitor");
|
||||
gtk_widget_set_tooltip_text(
|
||||
w,
|
||||
"Direct Monitor sends the analogue input signals to the "
|
||||
@@ -101,7 +113,7 @@ GtkWidget *create_iface_no_mixer_main(struct alsa_card *card) {
|
||||
"both inputs to the left and right outputs. Stereo sends "
|
||||
"input 1 to the left, and input 2 to the right output."
|
||||
);
|
||||
gtk_grid_attach(GTK_GRID(output_grid), w, 0, 1, 1, 1);
|
||||
gtk_grid_attach(GTK_GRID(output_grid), w, 0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,5 +124,5 @@ GtkWidget *create_iface_no_mixer_main(struct alsa_card *card) {
|
||||
GtkWidget *startup = create_startup_controls(card);
|
||||
gtk_window_set_child(GTK_WINDOW(card->window_startup), startup);
|
||||
|
||||
return grid;
|
||||
return top;
|
||||
}
|
||||
|
||||