From c4c9f024336b25a82f33e6dd0285560558e28f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Jan 2023 00:49:43 +0800 Subject: [PATCH] Sound (Linux): add dirty support --- CMakeLists.txt | 7 ++- completions/bash | 1 + src/common/init.c | 5 ++ src/data/config_user.txt | 1 + src/data/help.txt | 2 + src/detection/sound/sound_linux.c | 89 +++++++++++++++++++++++++++++++ src/fastfetch.h | 1 + 7 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/detection/sound/sound_linux.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 021c508f2..4d51173fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF) cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) +cmake_dependent_option(ENABLE_ALSA "Enable alsa-lib" ON "LINUX" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF) cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF) @@ -342,7 +343,7 @@ if(LINUX) src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_linux.c src/detection/qt.c - src/detection/sound/sound_nosupport.c + src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c @@ -662,6 +663,10 @@ ff_lib_enable(FREETYPE "freetype2" "FreeType2" ) +ff_lib_enable(ALSA + "alsa" + "ALSA" +) if(ENABLE_THREADS) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS) diff --git a/completions/bash b/completions/bash index 2542c6887..2b6db37c6 100644 --- a/completions/bash +++ b/completions/bash @@ -379,6 +379,7 @@ __fastfetch_completion() "--lib-glx" "--lib-osmesa" "--lib-opencl" + "--lib-alsa" "--battery-dir" ) diff --git a/src/common/init.c b/src/common/init.c index 63f866282..fc47c0888 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -140,6 +140,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.libOpenCL, 0); ffStrbufInitA(&instance->config.libcJSON, 0); ffStrbufInitA(&instance->config.libfreetype, 0); + ffStrbufInit(&instance->config.libAlsa); ffStrbufInit(&instance->config.libwlanapi); ffStrbufInit(&instance->config.libnm); @@ -407,6 +408,7 @@ static void destroyConfig(FFinstance* instance) ffStrbufDestroy(&instance->config.libOpenCL); ffStrbufDestroy(&instance->config.libcJSON); ffStrbufDestroy(&instance->config.libfreetype); + ffStrbufDestroy(&instance->config.libAlsa); ffStrbufDestroy(&instance->config.libwlanapi); ffStrbufDestroy(&instance->config.libnm); @@ -512,6 +514,9 @@ void ffListFeatures() #ifdef FF_HAVE_FREETYPE "freetype\n" #endif + #ifdef FF_HAVE_ALSA + "alsa-lib\n" + #endif #ifdef FF_HAVE_LIBNM "libnm\n" #endif diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 7bf147397..5ace73f0b 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -426,4 +426,5 @@ #--lib-osmesa /usr/lib/libOSMesa.so #--lib-opencl /usr/lib/libOpenCL.so #--lib-cjson /usr/lib/libcjson.so +#--lib-cjson /usr/lib/libasound.so #--lib-freetype /data/data/com.termux/files/usr/lib diff --git a/src/data/help.txt b/src/data/help.txt index d91b442ba..a8325cdc4 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -98,6 +98,8 @@ Library options: Set the path of a library to load --lib-osmesa --lib-opencl --lib-cjson + --lib-alsa + --lib-freetype Module specific options: --title-fqdn : Set if the title should use fully qualified domain name. Default is false diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c new file mode 100644 index 000000000..bf5a421d0 --- /dev/null +++ b/src/detection/sound/sound_linux.c @@ -0,0 +1,89 @@ +#include "sound.h" + +#ifdef FF_HAVE_ALSA + +#include "common/library.h" +#include "common/io.h" + +#include + +static const char* doDetectSound(const FFinstance* instance, FFlist* devices) +{ + FF_LIBRARY_LOAD(asound, &instance->config.libAlsa, "dlopen asound failed", "libasound" FF_LIBRARY_EXTENSION, 2); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_open); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_attach); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_register); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_load); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_first_elem); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_elem_next); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_is_active); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_playback_volume_range); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_playback_volume); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_name); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_close); + + snd_mixer_t *mixer; + if (ffsnd_mixer_open(&mixer, 0) < 0) + return "snd_mixer_open() failed"; + + if (ffsnd_mixer_attach(mixer, "default") < 0) + { + ffsnd_mixer_close(mixer); + return "snd_mixer_attach(\"default\") failed"; + } + + if (ffsnd_mixer_selem_register(mixer, NULL, NULL) < 0) + { + ffsnd_mixer_close(mixer); + return "snd_mixer_selem_register() failed"; + } + + if (ffsnd_mixer_load(mixer) < 0) + { + ffsnd_mixer_close(mixer); + return "snd_mixer_load() failed"; + } + + for (snd_mixer_elem_t* elem = ffsnd_mixer_first_elem(mixer); elem; elem = ffsnd_mixer_elem_next(elem)) + { + if (!ffsnd_mixer_selem_is_active(elem)) + continue; + + long min, max; + if (ffsnd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0) + continue; + + long volume; + if (ffsnd_mixer_selem_get_playback_volume(elem, 0, &volume) < 0) + continue; + + const char* name = ffsnd_mixer_selem_get_name(elem); + + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); + device->main = strcmp(name, "Master") == 0; + device->volume = (uint8_t) ((double)(volume - min) * 100.0 / (double)(max - min) + 0.5); + ffStrbufInitS(&device->name, name); + ffStrbufInit(&device->manufacturer); + } + + ffsnd_mixer_close(mixer); + return NULL; +} + +#endif // FF_HAVE_ALSA + +const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */) +{ + #ifdef FF_HAVE_ALSA + + ffSuppressIO(true); + const char* error = doDetectSound(instance, devices); + ffSuppressIO(false); + return error; + + #else + + return "Fastfetch was built without alsa support"; + + #endif +} diff --git a/src/fastfetch.h b/src/fastfetch.h index 54a27f85e..ffd30d30c 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -164,6 +164,7 @@ typedef struct FFconfig FFstrbuf libOpenCL; FFstrbuf libcJSON; FFstrbuf libfreetype; + FFstrbuf libAlsa; FFstrbuf libwlanapi; FFstrbuf libnm;