diff --git a/.gitignore b/.gitignore index 7f5ce74..362af8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ +*.tar.gz *.o .deps .gdb_history alsa-scarlett-gui alsa-scarlett-gui-resources.c +vu.b4.alsa-scarlett-gui.desktop diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8a86062 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +NAME := alsa-scarlett-gui +VERSION := $(shell git describe --abbrev=4 --always --tags | sed 's/-/./g') +NAMEVER := $(NAME)-$(VERSION) +TAR_FILE := $(NAMEVER).tar +TARGZ_FILE := $(TAR_FILE).gz +SPEC_FILE := $(NAME).spec + +default: + @echo "alsa-scarlett-gui" + @echo + @echo "If you want to build and install from source, please try:" + @echo " cd src" + @echo " make -j4" + @echo " sudo make install" + @echo + @echo "This Makefile knows about packaging:" + @echo " make tar" + @echo " make rpm" + +tar: $(TARGZ_FILE) + +$(TARGZ_FILE): + git archive --format=tar --prefix=$(NAMEVER)/ HEAD > $(TAR_FILE) + sed 's_VERSION$$_$(VERSION)_' < $(SPEC_FILE).template > $(SPEC_FILE) + tar --append -f $(TAR_FILE) \ + --transform s_^_$(NAMEVER)/_ \ + --owner=root --group=root \ + $(SPEC_FILE) + rm -f $(SPEC_FILE) + gzip < $(TAR_FILE) > $(TARGZ_FILE) + rm -f $(TAR_FILE) + +rpm: $(TARGZ_FILE) + rpmbuild -tb $(TARGZ_FILE) diff --git a/README.md b/README.md index 6d8bd25..9681b79 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ had 84 ALSA controls. Announcing the ALSA Scarlett Gen 2/3 Control Panel! +![Demonstration](img/demo.gif) + The GUI supports all features presented by the driver (if not, please report a bug). diff --git a/USAGE.md b/USAGE.md index df2f100..9395176 100644 --- a/USAGE.md +++ b/USAGE.md @@ -71,6 +71,19 @@ 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 +``` + ## No interface connected If no interface is detected (usually because there isn’t one @@ -442,3 +455,6 @@ menu option File → Interface Simulation to load. - 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. diff --git a/alsa-scarlett-gui.spec.template b/alsa-scarlett-gui.spec.template new file mode 100644 index 0000000..8d9754d --- /dev/null +++ b/alsa-scarlett-gui.spec.template @@ -0,0 +1,33 @@ +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 + +%description + +alsa-scarlett-gui is a Gtk4 GUI for the ALSA controls presented by the +Linux kernel Focusrite Scarlett Gen 2/3 Mixer Driver. + +%prep +%setup + +%build +make -C src -j4 VERSION=%{version} PREFIX=/usr + +%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 + +%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/alsa-scarlett-gui.png diff --git a/img/demo.gif b/img/demo.gif new file mode 100644 index 0000000..b40f5d3 Binary files /dev/null and b/img/demo.gif differ diff --git a/src/Makefile b/src/Makefile index b0173d8..32e87de 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,10 +1,15 @@ +# SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett +# SPDX-License-Identifier: GPL-3.0-or-later + # Credit to Tom Tromey and Paul D. Smith: # http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ +VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) DEPDIR := .deps DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d CFLAGS := -Wall -Werror -ggdb -fno-omit-frame-pointer -O2 -D_FORTIFY_SOURCE=2 +CFLAGS += -DVERSION=\"$(VERSION)\" PKG_CONFIG=pkg-config @@ -32,13 +37,14 @@ XML_OBJ := $(patsubst %.xml,%.c,$(XML_SRC)) SRCS := $(sort $(wildcard *.c) $(XML_OBJ)) OBJS := $(patsubst %.c,%.o,$(SRCS)) TARGET := alsa-scarlett-gui +DESKTOP_FILE := vu.b4.$(TARGET).desktop GLIB_COMPILE_RESOURCES := $(shell $(PKG_CONFIG) --variable=glib_compile_resources gio-2.0) -all: $(TARGET) +all: $(TARGET) $(DESKTOP_FILE) clean: - rm -f $(TARGET) $(OBJS) $(XML_OBJ) + rm -f $(TARGET) $(DESKTOP_FILE) $(OBJS) $(XML_OBJ) depclean: rm -rf $(DEPDIR) @@ -51,4 +57,37 @@ $(DEPFILES): include $(wildcard $(DEPFILES)) $(TARGET): $(OBJS) - cc ${LDFLAGS} -lm -o $(TARGET) $(OBJS) + cc -o $(TARGET) $(OBJS) ${LDFLAGS} -lm + +ifeq ($(PREFIX),) + PREFIX := /usr/local +endif + +BINDIR := $(DESTDIR)$(PREFIX)/bin +ICONTOP := $(DESTDIR)$(PREFIX)/share/icons/hicolor +ICONDIR := $(ICONTOP)/256x256/apps +DESKTOPDIR := $(DESTDIR)$(PREFIX)/share/applications + +$(DESKTOP_FILE): $(DESKTOP_FILE).template + sed 's_PREFIX_$(PREFIX)_' < $< > $@ + +install: all + install -d $(BINDIR) + install -m 755 $(TARGET) $(BINDIR) + install -d $(ICONDIR) + install -m 644 img/$(TARGET).png $(ICONDIR) + install -d $(DESKTOPDIR) + install -m 644 $(DESKTOP_FILE) $(DESKTOPDIR) + +uninstall: + rm -f $(BINDIR)/$(TARGET) + rm -f $(ICONDIR)/$(TARGET).png + rm -f $(DESKTOPDIR)/$(DESKTOP_FILE) + +help: + @echo "alsa-scarlett-gui" + @echo + @echo "This Makefile knows about:" + @echo " make" + @echo " make install" + @echo " make uninstall" diff --git a/src/about.c b/src/about.c index 11aee07..17d2b61 100644 --- a/src/about.c +++ b/src/about.c @@ -18,7 +18,7 @@ void activate_about( gtk_show_about_dialog( w, "program-name", "ALSA Scarlett Gen 2/3 Control Panel", - "version", "Version 0.1", + "version", "Version " VERSION, "comments", "GTK4 interface to the ALSA Scarlett Gen 2/3 Mixer controls", "website", "https://github.com/geoffreybennett/alsa-scarlett-gui", "copyright", "Copyright 2022 Geoffrey D. Bennett", @@ -29,4 +29,3 @@ void activate_about( NULL ); } - diff --git a/src/alsa-scarlett-gui-resources.xml b/src/alsa-scarlett-gui-resources.xml index 23df2ce..117f1d6 100644 --- a/src/alsa-scarlett-gui-resources.xml +++ b/src/alsa-scarlett-gui-resources.xml @@ -4,12 +4,6 @@ img/alsa-scarlett-gui-logo.png img/socket.svg - - img/alsa-scarlett-gui-48.png - - - img/alsa-scarlett-gui-256.png - alsa-scarlett-gui.css diff --git a/src/alsa-scarlett-gui.css b/src/alsa-scarlett-gui.css index 9c8bc72..1095484 100644 --- a/src/alsa-scarlett-gui.css +++ b/src/alsa-scarlett-gui.css @@ -1,4 +1,16 @@ -.route-label { font-size: smaller; } -.route-label:hover { background: #e0e0e0; } -.route-label:drop(active) { box-shadow: none; background: #e0e0e0; } -.button { padding: 0px 5px 0px 5px; } +.route-label { + font-size: smaller; +} + +.route-label:hover { + background: @theme_selected_bg_color; +} + +.route-label:drop(active) { + box-shadow: none; + background: @theme_selected_bg_color; +} + +button { + padding: 0px 5px 0px 5px; +} diff --git a/src/alsa.h b/src/alsa.h index 980ffd4..26408d6 100644 --- a/src/alsa.h +++ b/src/alsa.h @@ -95,8 +95,9 @@ struct routing_dst { // 0-based count within port_category int port_num; - // the mixer label widget for this destination - GtkWidget *mixer_label; + // the mixer label widgets for this destination + GtkWidget *mixer_label_top; + GtkWidget *mixer_label_bottom; }; // entry in alsa_card elems (ALSA control elements) array diff --git a/src/img/alsa-scarlett-gui-48.png b/src/img/alsa-scarlett-gui-48.png deleted file mode 100644 index e885630..0000000 Binary files a/src/img/alsa-scarlett-gui-48.png and /dev/null differ diff --git a/src/img/alsa-scarlett-gui-256.png b/src/img/alsa-scarlett-gui.png similarity index 100% rename from src/img/alsa-scarlett-gui-256.png rename to src/img/alsa-scarlett-gui.png diff --git a/src/main.c b/src/main.c index 4c979a4..c206dd1 100644 --- a/src/main.c +++ b/src/main.c @@ -30,7 +30,6 @@ static void load_css(void) { // gtk init static void startup(GtkApplication *app, gpointer user_data) { - gtk_window_set_default_icon_name("alsa-scarlett-gui"); gtk_application_set_menubar(app, G_MENU_MODEL(create_app_menu(app))); alsa_inotify_init(); diff --git a/src/vu.b4.alsa-scarlett-gui.desktop.template b/src/vu.b4.alsa-scarlett-gui.desktop.template new file mode 100644 index 0000000..5aeb414 --- /dev/null +++ b/src/vu.b4.alsa-scarlett-gui.desktop.template @@ -0,0 +1,9 @@ +[Desktop Entry] + +Encoding=UTF-8 +Value=1.5 +Type=Application +Name=ALSA Scarlett Gen 2/3 Control Panel +Icon=alsa-scarlett-gui +Exec=PREFIX/bin/alsa-scarlett-gui +Categories=GTK;AudioVideo;Audio;Mixer; diff --git a/src/window-mixer.c b/src/window-mixer.c index 0ab8ed9..23f25cd 100644 --- a/src/window-mixer.c +++ b/src/window-mixer.c @@ -39,13 +39,13 @@ GtkWidget *create_mixer_controls(struct alsa_card *card) { GtkWidget *l_left = gtk_label_new(name); gtk_grid_attach( GTK_GRID(mixer_top), l_left, - 0, i, 1, 1 + 0, i + 2, 1, 1 ); GtkWidget *l_right = gtk_label_new(name); gtk_grid_attach( GTK_GRID(mixer_top), l_right, - card->routing_out_count[PC_MIX] + 1, i, 1, 1 + card->routing_out_count[PC_MIX] + 1, i + 2, 1, 1 ); } @@ -74,7 +74,7 @@ GtkWidget *create_mixer_controls(struct alsa_card *card) { // create the gain control and attach to the grid GtkWidget *w = make_gain_alsa_elem(elem); - gtk_grid_attach(GTK_GRID(mixer_top), w, input_num + 1, mix_num, 1, 1); + gtk_grid_attach(GTK_GRID(mixer_top), w, input_num + 1, mix_num + 2, 1, 1); // look up the r_dst entry for the mixer input number struct routing_dst *r_dst = get_mixer_r_dst(card, input_num + 1); @@ -83,17 +83,22 @@ GtkWidget *create_mixer_controls(struct alsa_card *card) { continue; } - // lookup the label for the mixer input - GtkWidget *l = r_dst->mixer_label; + // lookup the top label for the mixer input + GtkWidget *l_top = r_dst->mixer_label_top; - // if the label doesn't already exist, create it and attach it to - // the bottom of the grid - if (!l) { - l = r_dst->mixer_label = gtk_label_new(""); + // if the top label doesn't already exist the bottom doesn't + // either; create them both and attach to the grid + if (!l_top) { + l_top = r_dst->mixer_label_top = gtk_label_new(""); + GtkWidget *l_bottom = r_dst->mixer_label_bottom = gtk_label_new(""); gtk_grid_attach( - GTK_GRID(mixer_top), l, - input_num, card->routing_in_count[PC_MIX] + input_num % 2, 3, 1 + GTK_GRID(mixer_top), l_top, + input_num, (input_num + 1) % 2, 3, 1 + ); + gtk_grid_attach( + GTK_GRID(mixer_top), l_bottom, + input_num, card->routing_in_count[PC_MIX] + input_num % 2 + 2, 3, 1 ); } } @@ -120,7 +125,9 @@ void update_mixer_labels(struct alsa_card *card) { card->routing_srcs, struct routing_src, routing_src_idx ); - if (r_dst->mixer_label) - gtk_label_set_text(GTK_LABEL(r_dst->mixer_label), r_src->name); + if (r_dst->mixer_label_top) { + gtk_label_set_text(GTK_LABEL(r_dst->mixer_label_top), r_src->name); + gtk_label_set_text(GTK_LABEL(r_dst->mixer_label_bottom), r_src->name); + } } } diff --git a/src/window-routing.c b/src/window-routing.c index 921f0e7..8acd1e7 100644 --- a/src/window-routing.c +++ b/src/window-routing.c @@ -334,9 +334,11 @@ static void create_routing_grid(struct alsa_card *card) { } static GtkWidget *make_socket_widget(void) { - return gtk_picture_new_for_resource( + GtkWidget *w = gtk_picture_new_for_resource( "/vu/b4/alsa-scarlett-gui/icons/socket.svg" ); + gtk_widget_set_align(w, GTK_ALIGN_CENTER, GTK_ALIGN_CENTER); + return w; } // something was dropped on a routing source