mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dbe24c7508 | |||
| d23d4ef5a0 | |||
| daac1b783c | |||
| 2e98dd7710 | |||
| 9d6d2ca5a4 | |||
| e4a1a836fe | |||
| 1e3cabff2d | |||
| 008cf3b83d | |||
| 3daede53eb | |||
| 36d9b5a9bd | |||
| 1826e23c29 | |||
| 43b3998b9d | |||
| c55cc9c732 | |||
| 0244e5ebd7 | |||
| ea6805de82 | |||
| 9aba57cdea | |||
| 0dffd8debf | |||
| 032ba375b6 | |||
| 743bc07bad | |||
| 044e5496fd | |||
| 102b2d33c7 | |||
| afc144fa01 | |||
| ededa4d6dd | |||
| af4596b666 |
@@ -13,7 +13,7 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
|
||||
+58
-5
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads
|
||||
|
||||
project(fastfetch
|
||||
VERSION 1.4.3
|
||||
VERSION 1.5.1
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
@@ -33,6 +33,10 @@ OPTION(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON)
|
||||
OPTION(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON)
|
||||
OPTION(ENABLE_ZLIB "Enable zlib" ON)
|
||||
OPTION(ENABLE_CHAFA "Enable chafa" ON)
|
||||
OPTION(ENABLE_EGL "Enable egl" ON)
|
||||
OPTION(ENABLE_GLX "Enable glx" ON)
|
||||
OPTION(ENABLE_OSMESA "Enable osmesa" ON)
|
||||
OPTION(ENABLE_OPENCL "Enable opencl" ON)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
@@ -123,6 +127,7 @@ add_library(libfastfetch STATIC
|
||||
src/detection/plasma.c
|
||||
src/detection/gtk.c
|
||||
src/detection/terminalShell.c
|
||||
src/detection/vulkan.c
|
||||
src/detection/media.c
|
||||
src/detection/datetime.c
|
||||
src/detection/displayserver/displayServer.c
|
||||
@@ -158,6 +163,7 @@ add_library(libfastfetch STATIC
|
||||
src/modules/disk.c
|
||||
src/modules/battery.c
|
||||
src/modules/locale.c
|
||||
src/modules/vulkan.c
|
||||
src/modules/localip.c
|
||||
src/modules/publicip.c
|
||||
src/modules/player.c
|
||||
@@ -166,6 +172,8 @@ add_library(libfastfetch STATIC
|
||||
src/modules/date.c
|
||||
src/modules/time.c
|
||||
src/modules/colors.c
|
||||
src/modules/opengl.c
|
||||
src/modules/opencl.c
|
||||
)
|
||||
|
||||
if(ENABLE_LIBPCI)
|
||||
@@ -333,11 +341,51 @@ if(ENABLE_ZLIB)
|
||||
endif()
|
||||
|
||||
if(ENABLE_CHAFA)
|
||||
pkg_check_modules(CHAFA chafa>=1.10)
|
||||
if(CHAFA_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CHAFA=1)
|
||||
if(IMAGEMAGICK6_FOUND OR IMAGEMAGICK7_FOUND)
|
||||
pkg_check_modules(CHAFA chafa>=1.10)
|
||||
if(CHAFA_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CHAFA=1)
|
||||
else()
|
||||
message(WARNING "Package chafa>=1.10 not found. Building without support.")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Package chafa>=1.10 not found. Building without support.")
|
||||
message(WARNING "Chafa not enabled, because neither ImageMagick6 nor ImageMagick7 were found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EGL)
|
||||
pkg_check_modules(EGL egl)
|
||||
if(EGL_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EGL=1)
|
||||
else()
|
||||
message(WARNING "Package egl not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_GLX)
|
||||
pkg_check_modules(GLX glx)
|
||||
if(GLX_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLX=1)
|
||||
else()
|
||||
message(WARNING "Package glx not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OSMESA)
|
||||
pkg_check_modules(OSMESA osmesa)
|
||||
if(OSMESA_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_OSMESA=1)
|
||||
else()
|
||||
message(WARNING "Package osmesa not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENCL)
|
||||
pkg_check_modules(OPENCL OpenCL)
|
||||
if(OPENCL_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_OPENCL=1)
|
||||
else()
|
||||
message(WARNING "Package opencl not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -362,6 +410,11 @@ target_include_directories(libfastfetch
|
||||
PRIVATE ${IMAGEMAGICK6_INCLUDE_DIRS}
|
||||
PRIVATE ${ZLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${CHAFA_INCLUDE_DIRS}
|
||||
PRIVATE ${VULKAN_INCLUDE_DIRS}
|
||||
PRIVATE ${EGL_INCLUDE_DIRS}
|
||||
PRIVATE ${GLX_INCLUDE_DIRS}
|
||||
PRIVATE ${OSMESA_INCLUDE_DIRS}
|
||||
PRIVATE ${OPENCL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(libfastfetch
|
||||
|
||||
@@ -14,7 +14,6 @@ Here i just add things that are easy to forget.
|
||||
- [ ] Better OS output for all possible combinations of /etc/os-release variables.
|
||||
- [ ] Expose temperatures to CPU format string
|
||||
- [ ] Expose temperatures to GPU format string
|
||||
- [ ] Fallback GPU detection using GL (multi GPU suport somehow possible?)
|
||||
- [ ] Find wayland compositor by looking at \${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY:-wayland-0}
|
||||
- [ ] Make LocalIP module more configurable
|
||||
- [ ] Automatic migrate old config files to newer versions
|
||||
|
||||
@@ -19,34 +19,38 @@ There are some presets defined for fastfech in [`presets`](presets), you can can
|
||||
Fastfetch dynamically loads needed libraries if they are available. Therefore its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and `libpthread`. They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions, so you probably don't have to worry about it.
|
||||
|
||||
The following libraries are used if present at runtime:
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Fallback for GPU output.
|
||||
* [`libxcb-randr`](https://xcb.freedesktop.org/),
|
||||
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
|
||||
[`libxcb`](https://xcb.freedesktop.org/),
|
||||
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support. The `libxcb*` ones usually have better performance.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
|
||||
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for rpm package count.
|
||||
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
|
||||
* [`libxcb-randr`](https://xcb.freedesktop.org/),
|
||||
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
|
||||
[`libxcb`](https://xcb.freedesktop.org/),
|
||||
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
|
||||
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
|
||||
* [`libEGL`](https://www.khronos.org/registry/EGL/),
|
||||
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
|
||||
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
|
||||
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for rpm package count.
|
||||
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||
|
||||
## Support status
|
||||
All categories not listed here should work without needing a specific implementation.
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Song, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Song, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
```
|
||||
|
||||
##### Logos
|
||||
```
|
||||
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Kubuntu, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Ubuntu, Void, Zorin
|
||||
Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Kubuntu, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Ubuntu, Void, Zorin
|
||||
```
|
||||
* Most of the logos have a small variant. Access it by appending _small to the logo name.
|
||||
* Some logos have an old variant. Access it by appending _old to the logo name.
|
||||
|
||||
@@ -130,6 +130,8 @@ __fastfetch_completion()
|
||||
"--localip-show-ipv4"
|
||||
"--localip-show-ipv6"
|
||||
"--localip-show-loop"
|
||||
"--escape-bedrock"
|
||||
"--pipe"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_STRING=(
|
||||
@@ -152,6 +154,7 @@ __fastfetch_completion()
|
||||
"-s"
|
||||
"--structure"
|
||||
"--set"
|
||||
"--gl"
|
||||
"--os-format"
|
||||
"--os-key"
|
||||
"--host-format"
|
||||
@@ -216,6 +219,12 @@ __fastfetch_completion()
|
||||
"--date-key"
|
||||
"--time-format"
|
||||
"--time-key"
|
||||
"--vulkan-key"
|
||||
"--vulkan-format"
|
||||
"--opengl-key"
|
||||
"--opengl-format"
|
||||
"--opencl-key"
|
||||
"--opencl-format"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_PATH=(
|
||||
@@ -236,6 +245,10 @@ __fastfetch_completion()
|
||||
"--lib-imagemagick"
|
||||
"--lib-z"
|
||||
"--lib-chafa"
|
||||
"--lib-egl"
|
||||
"--lib-glx"
|
||||
"--lib-osmesa"
|
||||
"--lib-opencl"
|
||||
"--battery-dir"
|
||||
"--load-config"
|
||||
)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Break:Colors
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Break:Colors
|
||||
|
||||
@@ -26,3 +26,6 @@
|
||||
--player-format "Name: {}"
|
||||
--song-format "Song: {}; Artist: {}; Album: {}"
|
||||
--datetime-format "year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}"
|
||||
--vulkan-format "driver: {}; Api Version: {}; Conformance Version: {}"
|
||||
--opengl-format "version: {}; renderer: {}; vendor: {}"
|
||||
--opencl-format "version: {}; device: {}; vendor: {}"
|
||||
|
||||
@@ -35,9 +35,6 @@ static void writeCacheFile(FFinstance* instance, const char* moduleName, const c
|
||||
|
||||
void ffCacheValidate(FFinstance* instance)
|
||||
{
|
||||
if(instance->config.recache)
|
||||
return;
|
||||
|
||||
FFstrbuf content;
|
||||
ffStrbufInit(&content);
|
||||
readCacheFile(instance, "cacheversion", "ffv", &content);
|
||||
|
||||
+48
-19
@@ -124,6 +124,9 @@ static void defaultConfig(FFinstance* instance)
|
||||
instance->config.allowSlowOperations = false;
|
||||
instance->config.disableLinewrap = true;
|
||||
instance->config.hideCursor = true;
|
||||
instance->config.escapeBedrock = true;
|
||||
instance->config.glType = FF_GL_TYPE_AUTO;
|
||||
instance->config.pipe = false;
|
||||
|
||||
ffStrbufInitA(&instance->config.osFormat, 0);
|
||||
ffStrbufInitA(&instance->config.osKey, 0);
|
||||
@@ -187,6 +190,12 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.dateFormat, 0);
|
||||
ffStrbufInitA(&instance->config.timeKey, 0);
|
||||
ffStrbufInitA(&instance->config.timeFormat, 0);
|
||||
ffStrbufInitA(&instance->config.vulkanKey, 0);
|
||||
ffStrbufInitA(&instance->config.vulkanFormat, 0);
|
||||
ffStrbufInitA(&instance->config.openGLKey, 0);
|
||||
ffStrbufInitA(&instance->config.openGLFormat, 0);
|
||||
ffStrbufInitA(&instance->config.openCLKey, 0);
|
||||
ffStrbufInitA(&instance->config.openCLFormat, 0);
|
||||
|
||||
ffStrbufInitA(&instance->config.libPCI, 0);
|
||||
ffStrbufInitA(&instance->config.libVulkan, 0);
|
||||
@@ -204,6 +213,10 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.libImageMagick, 0);
|
||||
ffStrbufInitA(&instance->config.libZ, 0);
|
||||
ffStrbufInitA(&instance->config.libChafa, 0);
|
||||
ffStrbufInitA(&instance->config.libEGL, 0);
|
||||
ffStrbufInitA(&instance->config.libGLX, 0);
|
||||
ffStrbufInitA(&instance->config.libOSMesa, 0);
|
||||
ffStrbufInitA(&instance->config.libOpenCL, 0);
|
||||
|
||||
ffStrbufInitA(&instance->config.diskFolders, 0);
|
||||
|
||||
@@ -228,29 +241,29 @@ void ffInitInstance(FFinstance* instance)
|
||||
defaultConfig(instance);
|
||||
}
|
||||
|
||||
static void resetConsole(bool disableLinewrap, bool hideCursor)
|
||||
{
|
||||
if(disableLinewrap)
|
||||
fputs("\033[?7h", stdout);
|
||||
|
||||
if(hideCursor)
|
||||
fputs("\033[?25h", stdout);
|
||||
}
|
||||
|
||||
static volatile bool ffDisableLinewrap = true;
|
||||
static volatile bool ffHideCursor = true;
|
||||
|
||||
static void resetConsole()
|
||||
{
|
||||
if(ffDisableLinewrap)
|
||||
fputs("\033[?7h", stdout);
|
||||
|
||||
if(ffHideCursor)
|
||||
fputs("\033[?25h", stdout);
|
||||
}
|
||||
|
||||
static void exitSignalHandler(int signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole(ffDisableLinewrap, ffHideCursor);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ffStart(FFinstance* instance)
|
||||
{
|
||||
ffDisableLinewrap = instance->config.disableLinewrap;
|
||||
ffHideCursor = instance->config.hideCursor;
|
||||
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
|
||||
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
|
||||
|
||||
struct sigaction action = {};
|
||||
action.sa_handler = exitSignalHandler;
|
||||
@@ -260,24 +273,28 @@ void ffStart(FFinstance* instance)
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
|
||||
//We do the cache validation here, so we can skip it if --recache is given
|
||||
ffCacheValidate(instance);
|
||||
if(!instance->config.recache)
|
||||
ffCacheValidate(instance);
|
||||
|
||||
//reset everything to default before we start printing
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
if(!instance->config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(instance->config.hideCursor)
|
||||
if(ffHideCursor)
|
||||
fputs("\033[?25l", stdout);
|
||||
|
||||
if(instance->config.disableLinewrap)
|
||||
if(ffDisableLinewrap)
|
||||
fputs("\033[?7l", stdout);
|
||||
|
||||
ffPrintLogo(instance);
|
||||
ffLogoPrint(instance);
|
||||
}
|
||||
|
||||
void ffFinish(FFinstance* instance)
|
||||
{
|
||||
ffPrintRemainingLogo(instance);
|
||||
resetConsole(instance->config.disableLinewrap, instance->config.hideCursor);
|
||||
if(instance->config.logoPrintRemaining)
|
||||
ffLogoPrintRemaining(instance);
|
||||
|
||||
resetConsole();
|
||||
}
|
||||
|
||||
//Must be in a file compiled with the libfastfetch target, because the FF_HAVE* macros are not defined for the executable targets
|
||||
@@ -335,6 +352,18 @@ void ffListFeatures()
|
||||
#ifdef FF_HAVE_RPM
|
||||
"rpm\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_EGL
|
||||
"egl\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_GLX
|
||||
"glx\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
"osmesa\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_OPENCL
|
||||
"opencl\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,32 @@ void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* mino
|
||||
ffStrbufAppend(buffer, patch);
|
||||
}
|
||||
|
||||
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2)
|
||||
{
|
||||
if(version1->major != version2->major)
|
||||
return version1->major > version2->major ? 1 : -1;
|
||||
|
||||
if(version1->minor != version2->minor)
|
||||
return version1->minor > version2->minor ? 1 : -1;
|
||||
|
||||
if(version1->patch != version2->patch)
|
||||
return version1->patch > version2->patch ? 1 : -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty)
|
||||
{
|
||||
if(version->major > 0 || version->minor > 0 || version->patch > 0)
|
||||
ffStrbufAppendF(pretty, "%u", version->major);
|
||||
|
||||
if(version->minor > 0 || version->patch > 0)
|
||||
ffStrbufAppendF(pretty, ".%u", version->minor);
|
||||
|
||||
if(version->patch > 0)
|
||||
ffStrbufAppendF(pretty, ".%u", version->patch);
|
||||
}
|
||||
|
||||
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
|
||||
{
|
||||
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
|
||||
{
|
||||
ffLogoPrintLine(instance);
|
||||
|
||||
if(!instance->config.pipe)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
ffPrintColor(&instance->config.mainColor);
|
||||
}
|
||||
|
||||
if(customKeyFormat == NULL || customKeyFormat->length == 0)
|
||||
{
|
||||
fputs(moduleName, stdout);
|
||||
|
||||
if(moduleIndex > 0)
|
||||
printf(" %hhu", moduleIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
ffParseFormatString(&key, customKeyFormat, NULL, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||
});
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
|
||||
if(!instance->config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
ffStrbufWriteTo(&instance->config.separator, stdout);
|
||||
|
||||
if(!instance->config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
}
|
||||
|
||||
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...)
|
||||
{
|
||||
if(!instance->config.showErrors)
|
||||
@@ -50,6 +87,11 @@ void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t m
|
||||
|
||||
void ffPrintColor(const FFstrbuf* colorValue)
|
||||
{
|
||||
//If the color is not set, this would reset in \033[m, which resets everything.
|
||||
//So we only print it, if the main color is at least one char.
|
||||
if(colorValue->length == 0)
|
||||
return;
|
||||
|
||||
fputs("\033[", stdout);
|
||||
ffStrbufWriteTo(colorValue, stdout);
|
||||
fputc('m', stdout);
|
||||
|
||||
+21
-11
@@ -90,24 +90,33 @@ bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
|
||||
|
||||
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
bool* searchedValues = malloc(sizeof(bool) * numQueries);
|
||||
bool valueStorage[4];
|
||||
bool* unsetValues;
|
||||
|
||||
if(numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
|
||||
unsetValues = malloc(sizeof(bool) * numQueries);
|
||||
else
|
||||
unsetValues = valueStorage;
|
||||
|
||||
bool allSet = true;
|
||||
for(uint32_t i = 0; i < numQueries; i++)
|
||||
{
|
||||
if((searchedValues[i] = queries[i].buffer->length == 0))
|
||||
if((unsetValues[i] = queries[i].buffer->length == 0))
|
||||
allSet = false;
|
||||
}
|
||||
|
||||
if(allSet)
|
||||
{
|
||||
free(searchedValues);
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE* file = fopen(filename, "r");
|
||||
if(file == NULL)
|
||||
return false;
|
||||
|
||||
if(allSet)
|
||||
{
|
||||
fclose(file);
|
||||
if(unsetValues != valueStorage)
|
||||
free(unsetValues);
|
||||
return true;
|
||||
}
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
@@ -115,7 +124,7 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
|
||||
{
|
||||
for(uint32_t i = 0; i < numQueries; i++)
|
||||
{
|
||||
if(!searchedValues[i])
|
||||
if(!unsetValues[i])
|
||||
continue;
|
||||
|
||||
uint32_t currentLength = queries[i].buffer->length;
|
||||
@@ -125,13 +134,14 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
|
||||
}
|
||||
}
|
||||
|
||||
free(searchedValues);
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(file);
|
||||
|
||||
if(unsetValues != valueStorage)
|
||||
free(unsetValues);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,18 @@
|
||||
# Default is the first match starting with org.mpris.MediaPlayer2.
|
||||
#--player-name spotify
|
||||
|
||||
# Escape bedrock option
|
||||
# Sets if fastfetch should escape the bedrock jail, if it detectes that it is running in one
|
||||
# Must be true or false.
|
||||
# Default is true.
|
||||
#--escape-bedrock true
|
||||
|
||||
# GL option
|
||||
# Sets with opengl context creation library to use
|
||||
# Must be either auto, egl, glx or osmesa
|
||||
# Default is auto.
|
||||
#--gl auto
|
||||
|
||||
# Key options:
|
||||
# Sets the displayed key of a module
|
||||
# Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help.
|
||||
@@ -183,6 +195,9 @@
|
||||
#--player-key Media Player
|
||||
#--song-key Song
|
||||
#--datetime-key Date Time
|
||||
#--vulkan-key Vulkan
|
||||
#--opengl-key OpenGL
|
||||
#--opencl-key OpenCL
|
||||
|
||||
# Format options:
|
||||
# Sets the format string for module values.
|
||||
@@ -218,6 +233,9 @@
|
||||
#--player-format
|
||||
#--song-format
|
||||
#--datetime-format
|
||||
#--vulkan-format
|
||||
#--opengl-format
|
||||
#--opencl-format
|
||||
|
||||
# Library options:
|
||||
# Sets an user specific path to a library to load.
|
||||
@@ -238,3 +256,7 @@
|
||||
#--lib-imagemagick /usr/lib/libMagickCore-7.Q16HDRI.so
|
||||
#--lib-z /usr/lib/libz.so
|
||||
#--lib-chafa /usr/lib/libchafa.so
|
||||
#--lib-egl /usr/lib/libEGL.so
|
||||
#--lib-glx /usr/lib/libGLX.so
|
||||
#--lib-osmesa /usr/lib/libOSMesa.so
|
||||
#--lib-opencl /usr/lib/libOpenCL.so
|
||||
@@ -18,6 +18,8 @@ General options:
|
||||
--load-config <file>: load a config file or a preset (+)
|
||||
--multithreading <?value>: use multiple threads to detect values
|
||||
--allow-slow-operations <?value>: allow operations that are usually very slow for more detailed output
|
||||
--escape-bedrock <?value>: on bedrock linux, sets if it should escape the bedrock jail or not
|
||||
--pipe <?value>: disable logo and all escape sequences
|
||||
|
||||
Logo options:
|
||||
-l,--logo <logo>: set the logo to use. The type is specified by --logo-type. If default: the name of a builtin logo or a path to a file
|
||||
@@ -76,6 +78,9 @@ Format options: Provide the format string for custom output. Use fastfetch --hel
|
||||
--datetime-format <format>
|
||||
--time-format <format>
|
||||
--date-format <format>
|
||||
--vulkan-format <format>
|
||||
--opengl-format <format>
|
||||
--opencl-format <format>
|
||||
|
||||
Key options: Provide a custom key for an output
|
||||
--os-key <key>
|
||||
@@ -109,6 +114,9 @@ Key options: Provide a custom key for an output
|
||||
--datetime-key <key>
|
||||
--time-key <key>
|
||||
--date-key <key>
|
||||
--vulkan-key <key>
|
||||
--opengl-key <key>
|
||||
--opencl-key <key>
|
||||
|
||||
Library options: Set the path of a library to load
|
||||
--lib-PCI <path>
|
||||
@@ -127,6 +135,10 @@ Library options: Set the path of a library to load
|
||||
--lib-imagemagick <path>
|
||||
--lib-z <path>
|
||||
--lib-chafa <path>
|
||||
--lib-egl <path>
|
||||
--lib-glx <path>
|
||||
--lib-osmesa <path>
|
||||
--lib-opencl <path>
|
||||
|
||||
Module specific options:
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
@@ -138,6 +150,7 @@ Module specific options:
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--player-name: The name of the player to use
|
||||
--gl <value>: Sets the opengl context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
|
||||
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||
If a value starts with a ?, it is optional. "true" will be used if not set.
|
||||
|
||||
@@ -17,6 +17,8 @@ Locale
|
||||
LocalIP
|
||||
Memory
|
||||
OS
|
||||
OpenCL
|
||||
OpenGL
|
||||
Packages
|
||||
Player
|
||||
Processes
|
||||
@@ -31,5 +33,6 @@ Theme
|
||||
Time
|
||||
Title
|
||||
Uptime
|
||||
Vulkan
|
||||
WM
|
||||
WMTheme
|
||||
|
||||
+15
-4
@@ -5,12 +5,12 @@
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
|
||||
static void parseFile(const char* fileName, FFOSResult* result)
|
||||
static bool parseFile(const char* fileName, FFOSResult* result)
|
||||
{
|
||||
if(result->name.length > 0 && result->prettyName.length > 0)
|
||||
return;
|
||||
if(result->id.length > 0 && result->name.length > 0 && result->prettyName.length > 0)
|
||||
return true;
|
||||
|
||||
ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
|
||||
return ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
|
||||
{"NAME =", &result->name},
|
||||
{"DISTRIB_DESCRIPTION =", &result->prettyName},
|
||||
{"PRETTY_NAME =", &result->prettyName},
|
||||
@@ -124,6 +124,17 @@ const FFOSResult* ffDetectOS(const FFinstance* instance)
|
||||
{
|
||||
parseFile(instance->config.osFile.chars, &result);
|
||||
}
|
||||
else if(instance->config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock/etc/bedrock-release", &result))
|
||||
{
|
||||
if(result.id.length == 0)
|
||||
ffStrbufAppendS(&result.id, "bedrock");
|
||||
|
||||
if(result.name.length == 0)
|
||||
ffStrbufAppendS(&result.name, "Bedrock");
|
||||
|
||||
if(result.prettyName.length == 0)
|
||||
ffStrbufAppendS(&result.prettyName, "Bedrock Linux");
|
||||
}
|
||||
else
|
||||
{
|
||||
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/os-release", &result);
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
static inline void applyVulkanVersion(uint32_t vulkanVersion, FFVersion* ffVersion)
|
||||
{
|
||||
ffVersion->major = VK_VERSION_MAJOR(vulkanVersion);
|
||||
ffVersion->minor = VK_VERSION_MINOR(vulkanVersion);
|
||||
ffVersion->patch = VK_VERSION_PATCH(vulkanVersion);
|
||||
}
|
||||
|
||||
static void applyDriverName(VkPhysicalDeviceDriverProperties* properties, FFstrbuf* result)
|
||||
{
|
||||
if(!ffStrSet(properties->driverName))
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(result, properties->driverName);
|
||||
|
||||
if(!ffStrSet(properties->driverInfo))
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(result, " [");
|
||||
ffStrbufAppendS(result, properties->driverInfo);
|
||||
ffStrbufAppendC(result, ']');
|
||||
}
|
||||
|
||||
static void detectVulkan(const FFinstance* instance, FFVulkanResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(vulkan, instance->config.libVulkan, , "libvulkan.so", 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetInstanceProcAddr,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkCreateInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkDestroyInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkEnumeratePhysicalDevices,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetPhysicalDeviceProperties,)
|
||||
|
||||
//Some drivers (nvdc) print messages to stdout
|
||||
//and thats the best way i found to disable that
|
||||
ffSuppressIO(true);
|
||||
|
||||
FFVersion instanceVersion = FF_VERSION_INIT;
|
||||
|
||||
//We need to get the function pointer this way, because it is only provided by vulkan 1.1 and higher.
|
||||
//a dlsym would fail on 1.0 implementations
|
||||
PFN_vkEnumerateInstanceVersion ffvkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) ffvkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
|
||||
if(ffvkEnumerateInstanceVersion != NULL)
|
||||
{
|
||||
uint32_t version;
|
||||
if(ffvkEnumerateInstanceVersion(&version) == VK_SUCCESS)
|
||||
applyVulkanVersion(version, &instanceVersion);
|
||||
}
|
||||
|
||||
const uint32_t projectVersion = VK_MAKE_VERSION(
|
||||
FASTFETCH_PROJECT_VERSION_MAJOR,
|
||||
FASTFETCH_PROJECT_VERSION_MINOR,
|
||||
FASTFETCH_PROJECT_VERSION_PATCH
|
||||
);
|
||||
|
||||
//We need to request 1.2 to get physicalDeviceDriverProperties
|
||||
uint32_t requestedVkVersion = VK_API_VERSION_1_0;
|
||||
if(instanceVersion.minor >= 2)
|
||||
requestedVkVersion = VK_API_VERSION_1_2;
|
||||
|
||||
const VkApplicationInfo applicationInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationName = FASTFETCH_PROJECT_NAME,
|
||||
.applicationVersion = projectVersion,
|
||||
.pEngineName = "vulkanPrintGPUs",
|
||||
.engineVersion = projectVersion,
|
||||
.apiVersion = requestedVkVersion
|
||||
};
|
||||
|
||||
const VkInstanceCreateInfo instanceCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationInfo = &applicationInfo,
|
||||
.enabledLayerCount = 0,
|
||||
.ppEnabledLayerNames = NULL,
|
||||
.enabledExtensionCount = 0,
|
||||
.ppEnabledExtensionNames = NULL,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
VkInstance vkInstance;
|
||||
if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS)
|
||||
{
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//if instance creation succeeded, but vkEnumerateInstanceVersion didn't, this means we are running against a vulkan 1.0 implementation
|
||||
//explicitly set this version, if no device is found, so we still have at least this info
|
||||
if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0)
|
||||
instanceVersion.major = 1;
|
||||
|
||||
uint32_t physicalDeviceCount;
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
|
||||
{
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
|
||||
{
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2");
|
||||
|
||||
FFVersion maxDeviceApiVersion = FF_VERSION_INIT;
|
||||
FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT;
|
||||
|
||||
for(uint32_t i = 0; i < physicalDeviceCount; i++)
|
||||
{
|
||||
//Get device properties.
|
||||
//On VK 1.2 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain.
|
||||
//This is required to get the driver name and conformance version.
|
||||
|
||||
VkPhysicalDeviceDriverProperties driverProperties;
|
||||
driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
|
||||
driverProperties.pNext = NULL;
|
||||
driverProperties.driverName[0] = '\0';
|
||||
driverProperties.conformanceVersion = (VkConformanceVersion) {0, 0, 0, 0};
|
||||
|
||||
VkPhysicalDeviceProperties2 physicalDeviceProperties;
|
||||
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
physicalDeviceProperties.pNext = &driverProperties;
|
||||
|
||||
if(ffvkGetPhysicalDeviceProperties2 != NULL)
|
||||
ffvkGetPhysicalDeviceProperties2(physicalDevices[i], &physicalDeviceProperties);
|
||||
else
|
||||
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties.properties);
|
||||
|
||||
//If the device api version is higher than the current highest device api version, overwrite it
|
||||
//In this case, also use the current device driver name as the shown driver name
|
||||
|
||||
FFVersion deviceAPIVersion = FF_VERSION_INIT;
|
||||
applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion);
|
||||
if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0)
|
||||
{
|
||||
maxDeviceApiVersion = deviceAPIVersion;
|
||||
applyDriverName(&driverProperties, &result->driver);
|
||||
}
|
||||
|
||||
//If the device conformance version is higher than the current highest device conformance version, overwrite it
|
||||
|
||||
FFVersion deviceConformanceVersion = FF_VERSION_INIT;
|
||||
deviceConformanceVersion.major = driverProperties.conformanceVersion.major;
|
||||
deviceConformanceVersion.minor = driverProperties.conformanceVersion.minor;
|
||||
deviceConformanceVersion.patch = driverProperties.conformanceVersion.patch;
|
||||
|
||||
if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0)
|
||||
maxDeviceConformanceVersion = deviceConformanceVersion;
|
||||
|
||||
//Add the device to the list of devices shown by the GPU module
|
||||
|
||||
//We don't want softare rasterizers to show up as physical gpu
|
||||
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(&result->devices);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
|
||||
}
|
||||
|
||||
//If the highest device version is lower than the instance version, use it as our vulkan version
|
||||
//otherwise the instance version is the vulkan version
|
||||
if(ffVersionCompare(&instanceVersion, &maxDeviceApiVersion) > 0)
|
||||
ffVersionToPretty(&maxDeviceApiVersion, &result->apiVersion);
|
||||
else
|
||||
ffVersionToPretty(&instanceVersion, &result->apiVersion);
|
||||
|
||||
//Use the highest device conformace version as our conformance version
|
||||
ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion);
|
||||
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance)
|
||||
{
|
||||
static FFVulkanResult result;
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.driver);
|
||||
ffStrbufInit(&result.apiVersion);
|
||||
ffStrbufInit(&result.conformanceVersion);
|
||||
ffListInit(&result.devices, sizeof(FFGPUResult));
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
detectVulkan(instance, &result);
|
||||
#else
|
||||
FF_UNUSED(instance);
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
+92
-4
@@ -93,7 +93,7 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "packages-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xps), {8}, (flatpak), {9} (snap)", 9,
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-user), {9} (nix-default), {10} (flatpak), {11} (snap)", 11,
|
||||
"Number of all packages",
|
||||
"Number of pacman packages",
|
||||
"Pacman branch on manjaro",
|
||||
@@ -101,6 +101,8 @@ static inline void printCommandHelp(const char* command)
|
||||
"Number of rpm packages",
|
||||
"Number of emerge packages",
|
||||
"Number of xbps packages",
|
||||
"Number of nix-user packages",
|
||||
"Number of nix-default packages",
|
||||
"Number of flatpak packages",
|
||||
"Number of snap packages"
|
||||
);
|
||||
@@ -343,6 +345,31 @@ static inline void printCommandHelp(const char* command)
|
||||
"second with leading zero"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "vulkan-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("vulkan", "{} (driver), {} (api version)", 3,
|
||||
"Driver name",
|
||||
"API version",
|
||||
"Conformance version"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "opengl-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("opengl", "{}", 3,
|
||||
"version",
|
||||
"renderer",
|
||||
"vendor",
|
||||
"shading language version"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "opencl-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("opencl", "{}", 3,
|
||||
"version",
|
||||
"device",
|
||||
"vendor"
|
||||
);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "No specific help for command %s provided\n", command);
|
||||
}
|
||||
@@ -673,17 +700,17 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
}
|
||||
else if(strcasecmp(key, "--list-logos") == 0)
|
||||
{
|
||||
ffListBuiltinLogos();
|
||||
ffLogoBuiltinList();
|
||||
exit(0);
|
||||
}
|
||||
else if(strcasecmp(key, "--list-logos-autocompletion") == 0)
|
||||
{
|
||||
ffListBuiltinLogosAutocompletion();
|
||||
ffLogoBuiltinListAutocompletion();
|
||||
exit(0);
|
||||
}
|
||||
else if(strcasecmp(key, "--print-logos") == 0)
|
||||
{
|
||||
ffPrintBuiltinLogos(instance);
|
||||
ffLogoBuiltinPrint(instance);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -708,13 +735,26 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
data->multithreading = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--allow-slow-operations") == 0)
|
||||
instance->config.allowSlowOperations = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--escape-bedrock") == 0)
|
||||
instance->config.escapeBedrock = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--pipe") == 0)
|
||||
instance->config.pipe = optionParseBoolean(value);
|
||||
|
||||
////////////////
|
||||
//Logo options//
|
||||
////////////////
|
||||
|
||||
else if(strcasecmp(key, "-l") == 0 || strcasecmp(key, "--logo") == 0)
|
||||
{
|
||||
optionParseString(key, value, &instance->config.logoSource);
|
||||
|
||||
//this is usally wanted when using the none logo
|
||||
if(strcasecmp(value, "none") == 0)
|
||||
{
|
||||
instance->config.logoPaddingRight = 0;
|
||||
instance->config.logoPaddingLeft = 0;
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(key, "--logo-type") == 0)
|
||||
{
|
||||
if(value == NULL)
|
||||
@@ -964,6 +1004,18 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.timeKey);
|
||||
else if(strcasecmp(key, "--time-format") == 0)
|
||||
optionParseString(key, value, &instance->config.timeFormat);
|
||||
else if(strcasecmp(key, "--vulkan-key") == 0)
|
||||
optionParseString(key, value, &instance->config.vulkanKey);
|
||||
else if(strcasecmp(key, "--vulkan-format") == 0)
|
||||
optionParseString(key, value, &instance->config.vulkanFormat);
|
||||
else if(strcasecmp(key, "--opengl-key") == 0)
|
||||
optionParseString(key, value, &instance->config.openGLKey);
|
||||
else if(strcasecmp(key, "--opengl-format") == 0)
|
||||
optionParseString(key, value, &instance->config.openGLFormat);
|
||||
else if(strcasecmp(key, "--opencl-key") == 0)
|
||||
optionParseString(key, value, &instance->config.openCLKey);
|
||||
else if(strcasecmp(key, "--opencl-format") == 0)
|
||||
optionParseString(key, value, &instance->config.openCLFormat);
|
||||
|
||||
///////////////////
|
||||
//Library options//
|
||||
@@ -1001,6 +1053,14 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.libZ);
|
||||
else if(strcasecmp(key, "--lib-chafa") == 0)
|
||||
optionParseString(key, value, &instance->config.libChafa);
|
||||
else if(strcasecmp(key, "--lib-egl") == 0)
|
||||
optionParseString(key, value, &instance->config.libEGL);
|
||||
else if(strcasecmp(key, "--lib-glx") == 0)
|
||||
optionParseString(key, value, &instance->config.libGLX);
|
||||
else if(strcasecmp(key, "--lib-osmesa") == 0)
|
||||
optionParseString(key, value, &instance->config.libOSMesa);
|
||||
else if(strcasecmp(key, "--lib-opencl") == 0)
|
||||
optionParseString(key, value, &instance->config.libOpenCL);
|
||||
|
||||
//////////////////
|
||||
//Module options//
|
||||
@@ -1024,6 +1084,28 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.playerName);
|
||||
else if(strcasecmp(key, "--public-ip-timeout") == 0)
|
||||
instance->config.publicIpTimeout = optionParseUInt32(key, value);
|
||||
else if(strcasecmp(key, "--gl") == 0)
|
||||
{
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <type>\n", key);
|
||||
exit(491);
|
||||
}
|
||||
|
||||
if(strcasecmp(value, "auto") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_AUTO;
|
||||
else if(strcasecmp(value, "egl") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_EGL;
|
||||
else if(strcasecmp(value, "glx") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_GLX;
|
||||
else if(strcasecmp(value, "osmesa") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_OSMESA;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: unknown gl type: %s\n", value);
|
||||
exit(492);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////
|
||||
//Unknown option//
|
||||
@@ -1165,6 +1247,12 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
|
||||
ffPrintTime(instance);
|
||||
else if(strcasecmp(line, "colors") == 0)
|
||||
ffPrintColors(instance);
|
||||
else if(strcasecmp(line, "vulkan") == 0)
|
||||
ffPrintVulkan(instance);
|
||||
else if(strcasecmp(line, "opengl") == 0)
|
||||
ffPrintOpenGL(instance);
|
||||
else if(strcasecmp(line, "opencl") == 0)
|
||||
ffPrintOpenCL(instance);
|
||||
else
|
||||
ffPrintError(instance, line, 0, NULL, NULL, 0, "<no implementation provided>");
|
||||
}
|
||||
|
||||
+61
-9
@@ -42,6 +42,14 @@ typedef enum FFLogoType
|
||||
FF_LOGO_TYPE_CHAFA //Image file, printed as ascii art using libchafa
|
||||
} FFLogoType;
|
||||
|
||||
typedef enum FFGLType
|
||||
{
|
||||
FF_GL_TYPE_AUTO,
|
||||
FF_GL_TYPE_EGL,
|
||||
FF_GL_TYPE_GLX,
|
||||
FF_GL_TYPE_OSMESA
|
||||
} FFGLType;
|
||||
|
||||
typedef struct FFconfig
|
||||
{
|
||||
FFstrbuf logoSource;
|
||||
@@ -53,7 +61,7 @@ typedef struct FFconfig
|
||||
uint32_t logoPaddingRight;
|
||||
bool logoPrintRemaining;
|
||||
|
||||
FFstrbuf mainColor; //If this is empty, ffPrintLogo will set it to the main color of the logo
|
||||
FFstrbuf mainColor; //If this is empty, ffLogoPrint will set it to the main color of the logo
|
||||
FFstrbuf separator;
|
||||
|
||||
bool showErrors;
|
||||
@@ -62,6 +70,9 @@ typedef struct FFconfig
|
||||
bool allowSlowOperations;
|
||||
bool disableLinewrap;
|
||||
bool hideCursor;
|
||||
bool escapeBedrock;
|
||||
FFGLType glType;
|
||||
bool pipe; //disables logo and all escape sequences
|
||||
|
||||
FFstrbuf osFormat;
|
||||
FFstrbuf osKey;
|
||||
@@ -125,6 +136,12 @@ typedef struct FFconfig
|
||||
FFstrbuf dateFormat;
|
||||
FFstrbuf timeKey;
|
||||
FFstrbuf timeFormat;
|
||||
FFstrbuf vulkanKey;
|
||||
FFstrbuf vulkanFormat;
|
||||
FFstrbuf openGLKey;
|
||||
FFstrbuf openGLFormat;
|
||||
FFstrbuf openCLKey;
|
||||
FFstrbuf openCLFormat;
|
||||
|
||||
FFstrbuf libPCI;
|
||||
FFstrbuf libVulkan;
|
||||
@@ -142,6 +159,10 @@ typedef struct FFconfig
|
||||
FFstrbuf libImageMagick;
|
||||
FFstrbuf libZ;
|
||||
FFstrbuf libChafa;
|
||||
FFstrbuf libEGL;
|
||||
FFstrbuf libGLX;
|
||||
FFstrbuf libOSMesa;
|
||||
FFstrbuf libOpenCL;
|
||||
|
||||
FFstrbuf diskFolders;
|
||||
|
||||
@@ -180,6 +201,14 @@ typedef struct FFinstance
|
||||
FFstate state;
|
||||
} FFinstance;
|
||||
|
||||
typedef struct FFVersion
|
||||
{
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t patch;
|
||||
} FFVersion;
|
||||
#define FF_VERSION_INIT ((FFVersion) {0})
|
||||
|
||||
typedef struct FFTitleResult
|
||||
{
|
||||
FFstrbuf userName;
|
||||
@@ -235,6 +264,21 @@ typedef struct FFTerminalShellResult
|
||||
FFstrbuf userShellVersion;
|
||||
} FFTerminalShellResult;
|
||||
|
||||
typedef struct FFGPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
FFstrbuf driver;
|
||||
} FFGPUResult;
|
||||
|
||||
typedef struct FFVulkanResult
|
||||
{
|
||||
FFstrbuf driver;
|
||||
FFstrbuf apiVersion;
|
||||
FFstrbuf conformanceVersion;
|
||||
FFlist devices; //List of FFGPUResult
|
||||
} FFVulkanResult;
|
||||
|
||||
typedef struct FFResolutionResult
|
||||
{
|
||||
uint32_t width;
|
||||
@@ -412,6 +456,7 @@ void ffSuppressIO(bool suppress); // Not thread safe!
|
||||
void ffGetTerminalResponse(const char* request, const char* format, ...);
|
||||
|
||||
//common/printing.c
|
||||
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat);
|
||||
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...);
|
||||
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, const FFstrbuf* error, uint32_t numArgs, const FFformatarg* arguments);
|
||||
void ffPrintColor(const FFstrbuf* colorValue);
|
||||
@@ -452,6 +497,9 @@ bool ffStrSet(const char* str);
|
||||
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
|
||||
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4);
|
||||
|
||||
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
|
||||
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||
|
||||
//common/processing.c
|
||||
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
|
||||
|
||||
@@ -477,15 +525,13 @@ bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
|
||||
// Logo functions //
|
||||
////////////////////
|
||||
|
||||
void ffPrintLogo(FFinstance* instance);
|
||||
void ffPrintRemainingLogo(FFinstance* instance);
|
||||
void ffLogoPrint(FFinstance* instance);
|
||||
void ffLogoPrintRemaining(FFinstance* instance);
|
||||
void ffLogoPrintLine(FFinstance* instance);
|
||||
|
||||
void ffPrintLogoLine(FFinstance* instance);
|
||||
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat);
|
||||
|
||||
void ffPrintBuiltinLogos(FFinstance* instance);
|
||||
void ffListBuiltinLogos();
|
||||
void ffListBuiltinLogosAutocompletion();
|
||||
void ffLogoBuiltinPrint(FFinstance* instance);
|
||||
void ffLogoBuiltinList();
|
||||
void ffLogoBuiltinListAutocompletion();
|
||||
|
||||
/////////////////////////
|
||||
// Detection functions //
|
||||
@@ -517,6 +563,9 @@ const FFMediaResult* ffDetectMedia(FFinstance* instance);
|
||||
//detection/dateTime.c
|
||||
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance);
|
||||
|
||||
//detection/vulkan.c
|
||||
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance);
|
||||
|
||||
//////////////////////
|
||||
// Module functions //
|
||||
//////////////////////
|
||||
@@ -564,5 +613,8 @@ void ffPrintTime(FFinstance* instance);
|
||||
void ffPrintLocalIp(FFinstance* instance);
|
||||
void ffPrintPublicIp(FFinstance* instance);
|
||||
void ffPrintColors(FFinstance* instance);
|
||||
void ffPrintVulkan(FFinstance* instance);
|
||||
void ffPrintOpenGL(FFinstance* instance);
|
||||
void ffPrintOpenCL(FFinstance* instance);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#define FASTFETCH_PROJECT_NAME "@PROJECT_NAME@"
|
||||
#define FASTFETCH_PROJECT_VERSION "@PROJECT_VERSION@"
|
||||
#define FASTFETCH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define FASTFETCH_PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define FASTFETCH_PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define FASTFETCH_PROJECT_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@"
|
||||
|
||||
#define FASTFETCH_TARGET_DIR_ROOT "@TARGET_DIR_ROOT@"
|
||||
|
||||
@@ -50,6 +50,8 @@ int main(int argc, char** argv)
|
||||
//ffPrintDateTime(&instance);
|
||||
//ffPrintDate(&instance);
|
||||
//ffPrintTime(&instance);
|
||||
//ffPrintVulkan(&instance);
|
||||
//ffPrintOpenGL(&instance);
|
||||
ffPrintBreak(&instance);
|
||||
ffPrintColors(&instance);
|
||||
|
||||
|
||||
+34
-202
@@ -1,25 +1,12 @@
|
||||
#include "logo.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct FFlogo
|
||||
{
|
||||
const char* data;
|
||||
const char** names; //Null terminated
|
||||
const char** builtinColors; //Null terminated
|
||||
bool performColorReplacement;
|
||||
} FFlogo;
|
||||
|
||||
#define FF_LOGO_INIT static FFlogo logo; static bool init = false; if(init) return &logo; init = true;
|
||||
#define FF_LOGO_NAMES(...) static const char* names[] = (const char*[]) { __VA_ARGS__, NULL }; logo.names = names;
|
||||
#define FF_LOGO_LINES(x) logo.data = x;
|
||||
#define FF_LOGO_COLORS(...) static const char* colors[] = (const char*[]) { __VA_ARGS__, NULL }; logo.builtinColors = colors;
|
||||
#define FF_LOGO_RETURN return &logo;
|
||||
|
||||
static const FFlogo* getLogoUnknown()
|
||||
const FFlogo* ffLogoBuiltinGetUnknown()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("unknown", "question mark", "?")
|
||||
@@ -239,6 +226,36 @@ static const FFlogo* getLogoArcoLinux()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoBedrock()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("bedrock", "bedrocklinux", "bedrock-linux")
|
||||
FF_LOGO_LINES(
|
||||
"--------------------------------------\n"
|
||||
"--------------------------------------\n"
|
||||
"--------------------------------------\n"
|
||||
"---$2\\\\\\\\\\\\\\\\\\\\\\\\$1-----------------------\n"
|
||||
"----$2\\\\\\ \\\\\\$1----------------------\n"
|
||||
"-----$2\\\\\\ \\\\\\$1---------------------\n"
|
||||
"------$2\\\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\$1------\n"
|
||||
"-------$2\\\\\\ \\\\\\$1-----\n"
|
||||
"--------$2\\\\\\ \\\\\\$1----\n"
|
||||
"---------$2\\\\\\ ______ \\\\\\$1---\n"
|
||||
"----------$2\\\\\\ ///$1---\n"
|
||||
"-----------$2\\\\\\ ///$1----\n"
|
||||
"------------$2\\\\\\ ///$1-----\n"
|
||||
"-------------$2\\\\\\////////////////$1------\n"
|
||||
"--------------------------------------\n"
|
||||
"--------------------------------------\n"
|
||||
"--------------------------------------"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"90", //grey
|
||||
"37" //white
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoCachyOS()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1412,13 +1429,11 @@ static const FFlogo* getLogoZorin()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
typedef const FFlogo*(*GetLogoMethod)();
|
||||
|
||||
static GetLogoMethod* getLogos()
|
||||
GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
{
|
||||
static GetLogoMethod logoMethods[] = {
|
||||
ffLogoBuiltinGetUnknown,
|
||||
getLogoNone,
|
||||
getLogoUnknown,
|
||||
getLogoAndroid,
|
||||
getLogoAndroidSmall,
|
||||
getLogoArch,
|
||||
@@ -1426,6 +1441,7 @@ static GetLogoMethod* getLogos()
|
||||
getLogoArcoLinux,
|
||||
getLogoArtix,
|
||||
getLogoArtixSmall,
|
||||
getLogoBedrock,
|
||||
getLogoCachyOS,
|
||||
getLogoCelOS,
|
||||
getLogoCentOS,
|
||||
@@ -1474,187 +1490,3 @@ static GetLogoMethod* getLogos()
|
||||
|
||||
return logoMethods;
|
||||
}
|
||||
|
||||
static bool logoHasName(const FFlogo* logo, const char* name)
|
||||
{
|
||||
const char** logoName = logo->names;
|
||||
|
||||
while(*logoName != NULL)
|
||||
{
|
||||
if(strcasecmp(*logoName, name) == 0)
|
||||
return true;
|
||||
++logoName;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const FFlogo* getBuiltinLogo(const char* name)
|
||||
{
|
||||
GetLogoMethod* methods = getLogos();
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
const FFlogo* logo = (*methods)();
|
||||
if(logoHasName(logo, name))
|
||||
return logo;
|
||||
++methods;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const FFlogo* detectBuiltinLogoWithVersion(const FFstrbuf* versionString, const FFstrbuf* name)
|
||||
{
|
||||
if(versionString->length == 0)
|
||||
return getBuiltinLogo(name->chars);
|
||||
|
||||
#define FF_PRINT_LOGO_VERSIONED_IF_EXISTS(newLogo, oldLogo, ver) \
|
||||
if(logoHasName(newLogo, name->chars)) \
|
||||
{ \
|
||||
long version = strtol(versionString->chars, NULL, 10); \
|
||||
return (version == 0 || version == LONG_MAX || version == LONG_MIN || version >= ver) ? newLogo : oldLogo; \
|
||||
}
|
||||
|
||||
FF_PRINT_LOGO_VERSIONED_IF_EXISTS(getLogoFedora(), getLogoFedoraOld(), 34)
|
||||
FF_PRINT_LOGO_VERSIONED_IF_EXISTS(getLogoMint(), getLogoMintOld(), 19)
|
||||
|
||||
return getBuiltinLogo(name->chars);
|
||||
}
|
||||
|
||||
static const FFlogo* detectBuiltinLogo(const FFinstance* instance)
|
||||
{
|
||||
static const FFlogo* logo;
|
||||
static bool detected = false;
|
||||
if(detected)
|
||||
return logo;
|
||||
|
||||
detected = true;
|
||||
|
||||
const FFOSResult* os = ffDetectOS(instance);
|
||||
|
||||
logo = detectBuiltinLogoWithVersion(&os->version, &os->name);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = detectBuiltinLogoWithVersion(&os->version, &os->id);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = detectBuiltinLogoWithVersion(&os->version, &os->idLike);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = detectBuiltinLogoWithVersion(&os->version, &os->systemName);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
return getLogoUnknown();
|
||||
}
|
||||
|
||||
void ffLogoSetMainColor(FFinstance* instance)
|
||||
{
|
||||
const FFlogo* logo = NULL;
|
||||
|
||||
if(instance->config.logoSource.length > 0)
|
||||
logo = getBuiltinLogo(instance->config.logoSource.chars);
|
||||
|
||||
if(logo == NULL)
|
||||
logo = detectBuiltinLogo(instance);
|
||||
|
||||
ffStrbufAppendS(&instance->config.mainColor, logo->builtinColors[0]);
|
||||
}
|
||||
|
||||
static void printLogoStruct(FFinstance* instance, const FFlogo* logo, bool doColorReplacement)
|
||||
{
|
||||
if(!doColorReplacement)
|
||||
{
|
||||
ffLogoPrint(instance, logo->data, false);
|
||||
return;
|
||||
}
|
||||
|
||||
const char** colors = logo->builtinColors;
|
||||
for(int i = 0; *colors != NULL && i < FASTFETCH_LOGO_MAX_COLORS; i++, colors++)
|
||||
{
|
||||
if(instance->config.logoColors[i].length == 0)
|
||||
ffStrbufAppendS(&instance->config.logoColors[i], *colors);
|
||||
}
|
||||
|
||||
ffLogoPrint(instance, logo->data, true);
|
||||
}
|
||||
|
||||
void ffLogoPrintUnknown(FFinstance* instance)
|
||||
{
|
||||
printLogoStruct(instance, getLogoUnknown(), false);
|
||||
}
|
||||
|
||||
bool ffLogoPrintBuiltinIfExists(FFinstance* instance)
|
||||
{
|
||||
const FFlogo* logo = getBuiltinLogo(instance->config.logoSource.chars);
|
||||
if(logo == NULL)
|
||||
return false;
|
||||
|
||||
printLogoStruct(instance, logo, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffLogoPrintBuiltinDetected(FFinstance* instance)
|
||||
{
|
||||
printLogoStruct(instance, detectBuiltinLogo(instance), true);
|
||||
}
|
||||
|
||||
void ffPrintBuiltinLogos(FFinstance* instance)
|
||||
{
|
||||
GetLogoMethod* methods = getLogos();
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
const FFlogo* logo = (*methods)();
|
||||
printf("\033[%sm%s:\033[0m\n", logo->builtinColors[0], logo->names[0]);
|
||||
printLogoStruct(instance, logo, true);
|
||||
ffPrintRemainingLogo(instance);
|
||||
|
||||
instance->state.logoHeight = 0;
|
||||
for(uint8_t i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
|
||||
ffStrbufClear(&instance->config.logoColors[i]);
|
||||
|
||||
puts("\n");
|
||||
++methods;
|
||||
}
|
||||
}
|
||||
|
||||
void ffListBuiltinLogos()
|
||||
{
|
||||
GetLogoMethod* methods = getLogos();
|
||||
|
||||
uint32_t counter = 0;
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
const FFlogo* logo = (*methods)();
|
||||
const char** names = logo->names;
|
||||
|
||||
printf("%u)%s ", counter, counter < 10 ? " " : "");
|
||||
++counter;
|
||||
|
||||
while(*names != NULL)
|
||||
{
|
||||
printf("\"%s\" ", *names);
|
||||
++names;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
++methods;
|
||||
}
|
||||
}
|
||||
|
||||
void ffListBuiltinLogosAutocompletion()
|
||||
{
|
||||
GetLogoMethod* methods = getLogos();
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
printf("%s\n", (*methods)()->names[0]);
|
||||
++methods;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ static bool printImageChafa(FFinstance* instance, FFLogoRequestData* requestData
|
||||
result.length = (uint32_t) str->len;
|
||||
result.chars = str->str;
|
||||
|
||||
ffLogoPrint(instance, result.chars, false);
|
||||
ffLogoPrintChars(instance, result.chars, false);
|
||||
writeCacheStrbuf(requestData, &result, FF_CACHE_FILE_CHAFA);
|
||||
|
||||
ffg_string_free(str, TRUE);
|
||||
@@ -412,7 +412,7 @@ static bool printCachedChars(FFinstance* instance, FFLogoRequestData* requestDat
|
||||
return false;
|
||||
}
|
||||
|
||||
ffLogoPrint(instance, content.chars, false);
|
||||
ffLogoPrintChars(instance, content.chars, false);
|
||||
ffStrbufDestroy(&content);
|
||||
return true;
|
||||
}
|
||||
@@ -499,12 +499,12 @@ static bool getCharacterPixelDimensions(FFLogoRequestData* requestData)
|
||||
return requestData->characterPixelWidth > 1.0 && requestData->characterPixelHeight > 1.0;
|
||||
}
|
||||
|
||||
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
{
|
||||
//Performance optimisation
|
||||
#ifndef FF_HAVE_CHAFA
|
||||
if(type == FF_LOGO_TYPE_CHAFA)
|
||||
return FF_LOGO_IMAGE_RESULT_INIT_ERROR;
|
||||
return false;
|
||||
#endif
|
||||
|
||||
FFLogoRequestData requestData;
|
||||
@@ -516,7 +516,7 @@ FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type
|
||||
(type != FF_LOGO_TYPE_CHAFA || instance->config.logoWidth == 0 || instance->config.logoHeight == 0) &&
|
||||
!getCharacterPixelDimensions(&requestData)
|
||||
)
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
return false;
|
||||
|
||||
requestData.logoPixelWidth = simpleCeil((double) instance->config.logoWidth * requestData.characterPixelWidth);
|
||||
requestData.logoPixelHeight = simpleCeil((double) instance->config.logoHeight * requestData.characterPixelHeight);
|
||||
@@ -530,7 +530,7 @@ FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type
|
||||
{
|
||||
//We can safely return here, because if realpath failed, we surely won't be able to read the file
|
||||
ffStrbufDestroy(&requestData.cacheDir);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
return false;
|
||||
}
|
||||
ffStrbufRecalculateLength(&requestData.cacheDir);
|
||||
if(!ffStrbufEndsWithC(&requestData.cacheDir, '/'))
|
||||
@@ -544,7 +544,7 @@ FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type
|
||||
if(!instance->config.recache && printCached(instance, &requestData))
|
||||
{
|
||||
ffStrbufDestroy(&requestData.cacheDir);
|
||||
return FF_LOGO_IMAGE_RESULT_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
FFLogoImageResult result = FF_LOGO_IMAGE_RESULT_INIT_ERROR;
|
||||
@@ -559,13 +559,13 @@ FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type
|
||||
#endif
|
||||
|
||||
ffStrbufDestroy(&requestData.cacheDir);
|
||||
return result;
|
||||
return result == FF_LOGO_IMAGE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#else //FF_HAVE_IMAGEMAGICK{6, 7}
|
||||
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
{
|
||||
FF_UNUSED(instance, type);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
return false;
|
||||
}
|
||||
#endif //FF_HAVE_IMAGEMAGICK{6, 7}
|
||||
|
||||
@@ -10,6 +10,13 @@
|
||||
#define MAGICKCORE_HDRI_ENABLE 1
|
||||
#define MAGICKCORE_QUANTUM_DEPTH 16
|
||||
|
||||
typedef enum FFLogoImageResult
|
||||
{
|
||||
FF_LOGO_IMAGE_RESULT_SUCCESS, //Logo printed
|
||||
FF_LOGO_IMAGE_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version
|
||||
FF_LOGO_IMAGE_RESULT_RUN_ERROR //Failed to load / convert image, cancle whole sixel code
|
||||
} FFLogoImageResult;
|
||||
|
||||
typedef struct FFLogoRequestData
|
||||
{
|
||||
FFLogoType type;
|
||||
@@ -44,5 +51,4 @@ FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoRequestData* r
|
||||
FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoRequestData* requestData);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+224
-92
@@ -1,8 +1,9 @@
|
||||
#include "logo.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
void ffLogoPrint(FFinstance* instance, const char* data, bool doColorReplacement)
|
||||
void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement)
|
||||
{
|
||||
uint32_t currentlineLength = 0;
|
||||
|
||||
@@ -145,137 +146,268 @@ void ffLogoPrint(FFinstance* instance, const char* data, bool doColorReplacement
|
||||
printf("\033[%uA", instance->state.logoHeight);
|
||||
}
|
||||
|
||||
static void logoPrintFile(FFinstance* instance, bool doColorReplacement)
|
||||
static void logoApplyMainColor(FFinstance* instance, const FFlogo* logo)
|
||||
{
|
||||
if(instance->config.mainColor.length == 0)
|
||||
ffStrbufAppendS(&instance->config.mainColor, logo->builtinColors[0]);
|
||||
}
|
||||
|
||||
static bool logoHasName(const FFlogo* logo, const char* name)
|
||||
{
|
||||
const char** logoName = logo->names;
|
||||
|
||||
while(*logoName != NULL)
|
||||
{
|
||||
if(strcasecmp(*logoName, name) == 0)
|
||||
return true;
|
||||
++logoName;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const FFlogo* logoGetBuiltin(const char* name)
|
||||
{
|
||||
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
const FFlogo* logo = (*methods)();
|
||||
|
||||
if(logoHasName(logo, name))
|
||||
return logo;
|
||||
|
||||
++methods;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const FFlogo* logoGetBuiltinDetected(FFinstance* instance)
|
||||
{
|
||||
const FFOSResult* os = ffDetectOS(instance);
|
||||
|
||||
const FFlogo* logo = logoGetBuiltin(os->id.chars);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = logoGetBuiltin(os->name.chars);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = logoGetBuiltin(os->prettyName.chars);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = logoGetBuiltin(os->idLike.chars);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
logo = logoGetBuiltin(os->systemName.chars);
|
||||
if(logo != NULL)
|
||||
return logo;
|
||||
|
||||
return ffLogoBuiltinGetUnknown();
|
||||
}
|
||||
|
||||
static inline void logoApplyMainColorDetected(FFinstance* instance)
|
||||
{
|
||||
logoApplyMainColor(instance, logoGetBuiltinDetected(instance));
|
||||
}
|
||||
|
||||
static void logoPrintStruct(FFinstance* instance, const FFlogo* logo)
|
||||
{
|
||||
logoApplyMainColor(instance, logo);
|
||||
|
||||
const char** colors = logo->builtinColors;
|
||||
for(int i = 0; *colors != NULL && i < FASTFETCH_LOGO_MAX_COLORS; i++, colors++)
|
||||
{
|
||||
if(instance->config.logoColors[i].length == 0)
|
||||
ffStrbufAppendS(&instance->config.logoColors[i], *colors);
|
||||
}
|
||||
|
||||
ffLogoPrintChars(instance, logo->data, true);
|
||||
}
|
||||
|
||||
static bool logoPrintBuiltinIfExists(FFinstance* instance, const char* name)
|
||||
{
|
||||
const FFlogo* logo = logoGetBuiltin(name);
|
||||
if(logo == NULL)
|
||||
return false;
|
||||
|
||||
logoPrintStruct(instance, logo);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void logoPrintDetected(FFinstance* instance)
|
||||
{
|
||||
logoPrintStruct(instance, logoGetBuiltinDetected(instance));
|
||||
}
|
||||
|
||||
static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInitA(&content, 2047);
|
||||
|
||||
if(ffAppendFileContent(instance->config.logoSource.chars, &content))
|
||||
ffLogoPrint(instance, content.chars, doColorReplacement);
|
||||
else
|
||||
ffLogoPrintUnknown(instance);
|
||||
if(!ffAppendFileContent(instance->config.logoSource.chars, &content))
|
||||
{
|
||||
ffStrbufDestroy(&content);
|
||||
return false;
|
||||
}
|
||||
|
||||
logoApplyMainColorDetected(instance);
|
||||
ffLogoPrintChars(instance, content.chars, doColorReplacement);
|
||||
ffStrbufDestroy(&content);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void logoPrintDetected(FFinstance* instance)
|
||||
static bool logoPrintImageIfExists(FFinstance* instance, FFLogoType logoType)
|
||||
{
|
||||
//If no logo source is given, detect the logo from OS and print the right builtin one
|
||||
if(instance->config.logoSource.length == 0)
|
||||
if(!ffLogoPrintImageIfExists(instance, logoType))
|
||||
return false;
|
||||
|
||||
logoApplyMainColorDetected(instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void logoPrintKnownType(FFinstance* instance)
|
||||
{
|
||||
bool successfull;
|
||||
|
||||
if(instance->config.logoType == FF_LOGO_TYPE_BUILTIN)
|
||||
successfull = logoPrintBuiltinIfExists(instance, instance->config.logoSource.chars);
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_FILE)
|
||||
successfull = logoPrintFileIfExists(instance, true);
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_RAW)
|
||||
successfull = logoPrintFileIfExists(instance, false);
|
||||
else //image
|
||||
successfull = logoPrintImageIfExists(instance, instance->config.logoType);
|
||||
|
||||
if(!successfull)
|
||||
logoPrintDetected(instance);
|
||||
}
|
||||
|
||||
void ffLogoPrint(FFinstance* instance)
|
||||
{
|
||||
//In pipe mode, we don't have a logo or padding.
|
||||
//We also don't need to set main color, because it won't be printed anyway.
|
||||
//So we can return quickly here.
|
||||
if(instance->config.pipe)
|
||||
{
|
||||
ffLogoPrintBuiltinDetected(instance);
|
||||
instance->state.logoHeight = 0;
|
||||
instance->state.logoWidth = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//If a logo source is given, first look if it is the name of a builtin logo
|
||||
if(ffLogoPrintBuiltinIfExists(instance))
|
||||
//If the source is not set, we can directly print the detected logo.
|
||||
if(instance->config.logoSource.length == 0)
|
||||
{
|
||||
logoPrintDetected(instance);
|
||||
return;
|
||||
}
|
||||
|
||||
//If the source and source type is set to something else than auto, always print with the set type.
|
||||
if(instance->config.logoSource.length > 0 && instance->config.logoType != FF_LOGO_TYPE_AUTO)
|
||||
{
|
||||
logoPrintKnownType(instance);
|
||||
return;
|
||||
}
|
||||
|
||||
//If source matches the name of a builtin logo, print it and return.
|
||||
if(logoPrintBuiltinIfExists(instance, instance->config.logoSource.chars))
|
||||
return;
|
||||
|
||||
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell(instance);
|
||||
|
||||
FFLogoImageResult imageResult = FF_LOGO_IMAGE_RESULT_INIT_ERROR;
|
||||
|
||||
//Terminals that are known to support kitty graphics protocol
|
||||
//Try to load the logo as image.
|
||||
if(
|
||||
//Terminal emulators that support kitty graphics protocol.
|
||||
bool supportsKitty =
|
||||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0 ||
|
||||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0 ||
|
||||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm") == 0 ||
|
||||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0
|
||||
) {
|
||||
imageResult = ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_KITTY);
|
||||
if(imageResult == FF_LOGO_IMAGE_RESULT_SUCCESS)
|
||||
return;
|
||||
}
|
||||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0;
|
||||
|
||||
//If the logo can be loaded as an image, convert it to ascii art.
|
||||
//This happens in all terminals, that don't support kitty graphics protocol
|
||||
if(
|
||||
imageResult != FF_LOGO_IMAGE_RESULT_RUN_ERROR &&
|
||||
ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_CHAFA) == FF_LOGO_IMAGE_RESULT_SUCCESS
|
||||
) return;
|
||||
//Try to load the logo as an image. If it succeeds, print it and return.
|
||||
if(logoPrintImageIfExists(instance, supportsKitty ? FF_LOGO_TYPE_KITTY : FF_LOGO_TYPE_CHAFA))
|
||||
return;
|
||||
|
||||
//Print the content of the file as logo
|
||||
logoPrintFile(instance, true);
|
||||
//Try to load the logo as a file. If it succeeds, print it and return.
|
||||
if(logoPrintFileIfExists(instance, true))
|
||||
return;
|
||||
|
||||
logoPrintDetected(instance);
|
||||
}
|
||||
|
||||
void ffPrintLogo(FFinstance* instance)
|
||||
{
|
||||
if(instance->config.mainColor.length == 0)
|
||||
ffLogoSetMainColor(instance);
|
||||
|
||||
if( //Logo type needs set logo name, but nothing was given. Print question mark
|
||||
instance->config.logoType != FF_LOGO_TYPE_AUTO &&
|
||||
instance->config.logoSource.length == 0
|
||||
)
|
||||
ffLogoPrintUnknown(instance);
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_BUILTIN)
|
||||
{
|
||||
if(!ffLogoPrintBuiltinIfExists(instance))
|
||||
ffLogoPrintUnknown(instance);
|
||||
}
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_FILE)
|
||||
logoPrintFile(instance, true);
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_RAW)
|
||||
logoPrintFile(instance, false);
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_SIXEL || instance->config.logoType == FF_LOGO_TYPE_KITTY || instance->config.logoType == FF_LOGO_TYPE_CHAFA)
|
||||
{
|
||||
if(ffLogoPrintImageIfExists(instance, instance->config.logoType) != FF_LOGO_IMAGE_RESULT_SUCCESS)
|
||||
ffLogoPrintBuiltinDetected(instance);
|
||||
}
|
||||
else
|
||||
logoPrintDetected(instance);
|
||||
}
|
||||
|
||||
static inline void printLogoWidth(const FFinstance* instance)
|
||||
void ffLogoPrintLine(FFinstance* instance)
|
||||
{
|
||||
if(instance->state.logoWidth > 0)
|
||||
printf("\033[%uC", instance->state.logoWidth);
|
||||
|
||||
++instance->state.keysHeight;
|
||||
}
|
||||
|
||||
void ffPrintRemainingLogo(FFinstance* instance)
|
||||
void ffLogoPrintRemaining(FFinstance* instance)
|
||||
{
|
||||
if(!instance->config.logoPrintRemaining)
|
||||
return;
|
||||
|
||||
for(uint32_t i = instance->state.keysHeight; i <= instance->state.logoHeight; i++)
|
||||
while(instance->state.keysHeight < instance->state.logoHeight)
|
||||
{
|
||||
printLogoWidth(instance);
|
||||
ffLogoPrintLine(instance);
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintLogoLine(FFinstance* instance)
|
||||
void ffLogoBuiltinPrint(FFinstance* instance)
|
||||
{
|
||||
printLogoWidth(instance);
|
||||
++instance->state.keysHeight;
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
const FFlogo* logo = (*methods)();
|
||||
printf("\033[%sm%s:\033[0m\n", logo->builtinColors[0], logo->names[0]);
|
||||
logoPrintStruct(instance, logo);
|
||||
ffLogoPrintRemaining(instance);
|
||||
|
||||
//reset everything
|
||||
instance->state.logoHeight = 0;
|
||||
instance->state.keysHeight = 0;
|
||||
for(uint8_t i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
|
||||
ffStrbufClear(&instance->config.logoColors[i]);
|
||||
|
||||
puts("\n");
|
||||
++methods;
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
|
||||
void ffLogoBuiltinList()
|
||||
{
|
||||
ffPrintLogoLine(instance);
|
||||
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
||||
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
ffPrintColor(&instance->config.mainColor);
|
||||
uint32_t counter = 0;
|
||||
|
||||
if(customKeyFormat == NULL || customKeyFormat->length == 0)
|
||||
while(*methods != NULL)
|
||||
{
|
||||
fputs(moduleName, stdout);
|
||||
const FFlogo* logo = (*methods)();
|
||||
const char** names = logo->names;
|
||||
|
||||
if(moduleIndex > 0)
|
||||
printf(" %hhu", moduleIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
ffParseFormatString(&key, customKeyFormat, NULL, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||
});
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
printf("%u)%s ", counter, counter < 10 ? " " : "");
|
||||
++counter;
|
||||
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
ffStrbufWriteTo(&instance->config.separator, stdout);
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
while(*names != NULL)
|
||||
{
|
||||
printf("\"%s\" ", *names);
|
||||
++names;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
++methods;
|
||||
}
|
||||
}
|
||||
|
||||
void ffLogoBuiltinListAutocompletion()
|
||||
{
|
||||
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
||||
|
||||
while(*methods != NULL)
|
||||
{
|
||||
printf("%s\n", (*methods)()->names[0]);
|
||||
++methods;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-14
@@ -5,24 +5,23 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFlogo
|
||||
{
|
||||
const char* data;
|
||||
const char** names; //Null terminated
|
||||
const char** builtinColors; //Null terminated
|
||||
} FFlogo;
|
||||
|
||||
typedef const FFlogo*(*GetLogoMethod)();
|
||||
|
||||
//logo.c
|
||||
void ffLogoPrint(FFinstance* instance, const char* data, bool doColorReplacement);
|
||||
void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement);
|
||||
|
||||
//builtin.c
|
||||
void ffLogoSetMainColor(FFinstance* instance);
|
||||
|
||||
void ffLogoPrintUnknown(FFinstance* instance);
|
||||
bool ffLogoPrintBuiltinIfExists(FFinstance* instance);
|
||||
void ffLogoPrintBuiltinDetected(FFinstance* instance);
|
||||
|
||||
typedef enum FFLogoImageResult
|
||||
{
|
||||
FF_LOGO_IMAGE_RESULT_SUCCESS, //Logo printed
|
||||
FF_LOGO_IMAGE_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version
|
||||
FF_LOGO_IMAGE_RESULT_RUN_ERROR //Failed to load / convert image, cancle whole sixel code
|
||||
} FFLogoImageResult;
|
||||
const FFlogo* ffLogoBuiltinGetUnknown();
|
||||
GetLogoMethod* ffLogoBuiltinGetAll();
|
||||
|
||||
//image/image.c
|
||||
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type);
|
||||
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
|
||||
void ffPrintBreak(FFinstance* instance)
|
||||
{
|
||||
ffPrintLogoLine(instance);
|
||||
ffLogoPrintLine(instance);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
+11
-2
@@ -2,7 +2,16 @@
|
||||
|
||||
void ffPrintColors(FFinstance* instance)
|
||||
{
|
||||
ffPrintLogoLine(instance);
|
||||
if(instance->config.pipe)
|
||||
{
|
||||
ffLogoPrintLine(instance);
|
||||
puts("████████████████████████");
|
||||
ffLogoPrintLine(instance);
|
||||
puts("████████████████████████");
|
||||
return;
|
||||
}
|
||||
|
||||
ffLogoPrintLine(instance);
|
||||
|
||||
// 4%d: Set the background color
|
||||
// 3%d: Set the foreground color
|
||||
@@ -11,7 +20,7 @@ void ffPrintColors(FFinstance* instance)
|
||||
|
||||
puts(FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
|
||||
ffPrintLogoLine(instance);
|
||||
ffLogoPrintLine(instance);
|
||||
|
||||
// 1: Set everything to bolt. This causes normal colors on some systems to be bright.
|
||||
// 4%d: Set the backgound to the not bright color
|
||||
|
||||
+119
-194
@@ -5,181 +5,7 @@
|
||||
#define FF_GPU_MODULE_NAME "GPU"
|
||||
#define FF_GPU_NUM_FORMAT_ARGS 5
|
||||
|
||||
typedef struct GPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
FFstrbuf driver;
|
||||
} GPUResult;
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
static void vulkanFillGPUs(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_LIBRARY_LOAD(vulkan, instance->config.libVulkan, , "libvulkan.so", 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkCreateInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkDestroyInstance,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkEnumeratePhysicalDevices,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(vulkan, vkGetPhysicalDeviceProperties,)
|
||||
|
||||
//Some drivers (nvdc) print messages to stdout
|
||||
//and thats the best way i found to disable that
|
||||
ffSuppressIO(true);
|
||||
|
||||
const VkApplicationInfo applicationInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationName = FASTFETCH_PROJECT_NAME,
|
||||
.applicationVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_VERSION_MAJOR, 0, 0),
|
||||
.pEngineName = "vulkanPrintGPUs",
|
||||
.engineVersion = VK_MAKE_VERSION(FASTFETCH_PROJECT_VERSION_MAJOR, 0, 0),
|
||||
.apiVersion = VK_API_VERSION_1_0,
|
||||
};
|
||||
|
||||
const VkInstanceCreateInfo instanceCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.pApplicationInfo = &applicationInfo,
|
||||
.enabledLayerCount = 0,
|
||||
.ppEnabledLayerNames = NULL,
|
||||
.enabledExtensionCount = 0,
|
||||
.ppEnabledExtensionNames = NULL,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
VkInstance vkInstance;
|
||||
if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS)
|
||||
{
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t physicalDeviceCount;
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
|
||||
{
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
|
||||
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
|
||||
{
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < physicalDeviceCount; i++)
|
||||
{
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties);
|
||||
|
||||
//We don't want softare rasterizers
|
||||
if(physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||
continue;
|
||||
|
||||
GPUResult* result = ffListAdd(results);
|
||||
ffStrbufInit(&result->vendor);
|
||||
ffStrbufInit(&result->name);
|
||||
ffStrbufInit(&result->driver);
|
||||
|
||||
ffStrbufAppendS(&result->name, physicalDeviceProperties.deviceName);
|
||||
}
|
||||
|
||||
free(physicalDevices);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
dlclose(vulkan);
|
||||
ffSuppressIO(false);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include <pci/pci.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//see https://github.com/pciutils/pciutils/blob/5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b/ls-kernel.c#L220
|
||||
static void pciGetDriver(struct pci_dev* dev, FFstrbuf* driver, char*(*ffpci_get_param)(struct pci_access*, char*))
|
||||
{
|
||||
if(dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
|
||||
return;
|
||||
|
||||
const char* base = ffpci_get_param(dev->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, dev->domain, dev->bus, dev->dev, dev->func);
|
||||
|
||||
ffStrbufEnsureFree(driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, driver->chars, driver->allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
driver->length = (uint32_t) resultLength;
|
||||
driver->chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(driver, '/');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static void pciFillGPUs(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_LIBRARY_LOAD(pci, instance->config.libPCI, , "libpci.so", 4)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_get_param,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup,)
|
||||
|
||||
struct pci_access *pacc = ffpci_alloc();
|
||||
ffpci_init(pacc);
|
||||
ffpci_scan_bus(pacc);
|
||||
|
||||
struct pci_dev* dev;
|
||||
for (dev=pacc->devices; dev; dev=dev->next)
|
||||
{
|
||||
ffpci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS);
|
||||
char class[1024];
|
||||
ffpci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class);
|
||||
if(
|
||||
strcasecmp("VGA compatible controller", class) == 0 ||
|
||||
strcasecmp("3D controller", class) == 0 ||
|
||||
strcasecmp("Display controller", class) == 0
|
||||
) {
|
||||
GPUResult* result = ffListAdd(results);
|
||||
|
||||
ffStrbufInitA(&result->vendor, 256);
|
||||
ffpci_lookup_name(pacc, result->vendor.chars, (int) result->vendor.allocated -1, PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->vendor);
|
||||
|
||||
ffStrbufInitA(&result->name, 256);
|
||||
ffpci_lookup_name(pacc, result->name.chars, (int) result->name.allocated - 1, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->name);
|
||||
|
||||
ffStrbufInit(&result->driver);
|
||||
if(instance->config.gpuFormat.length > 0) //We only need it for the format string, so don't detect it if it isn't needed
|
||||
pciGetDriver(dev, &result->driver, ffpci_get_param);
|
||||
};
|
||||
}
|
||||
|
||||
ffpci_cleanup(pacc);
|
||||
dlclose(pci);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, GPUResult* result)
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* result)
|
||||
{
|
||||
const char* vendorPretty;
|
||||
if(ffStrbufIgnCaseCompS(&result->vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0)
|
||||
@@ -222,32 +48,131 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
|
||||
ffStrbufDestroy(&namePretty);
|
||||
}
|
||||
|
||||
static void printGPUList(FFinstance* instance, const FFlist* list)
|
||||
{
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
for(uint8_t i = 0; i < (uint8_t) list->length; i++)
|
||||
printGPUResult(instance, list->length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(list, i));
|
||||
|
||||
ffCacheClose(&cache);
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include <pci/pci.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//see https://github.com/pciutils/pciutils/blob/5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b/ls-kernel.c#L220
|
||||
static void pciGetDriver(struct pci_dev* dev, FFstrbuf* driver, char*(*ffpci_get_param)(struct pci_access*, char*))
|
||||
{
|
||||
if(dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
|
||||
return;
|
||||
|
||||
const char* base = ffpci_get_param(dev->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, dev->domain, dev->bus, dev->dev, dev->func);
|
||||
|
||||
ffStrbufEnsureFree(driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, driver->chars, driver->allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
driver->length = (uint32_t) resultLength;
|
||||
driver->chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(driver, '/');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static bool pciPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(pci, instance->config.libPCI, false, "libpci.so", 4)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_get_param, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup, false)
|
||||
|
||||
FFlist results;
|
||||
ffListInit(&results, sizeof(FFGPUResult));
|
||||
|
||||
struct pci_access *pacc = ffpci_alloc();
|
||||
ffpci_init(pacc);
|
||||
ffpci_scan_bus(pacc);
|
||||
|
||||
struct pci_dev* dev;
|
||||
for (dev=pacc->devices; dev; dev=dev->next)
|
||||
{
|
||||
ffpci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS);
|
||||
char class[1024];
|
||||
ffpci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class);
|
||||
if(
|
||||
strcasecmp("VGA compatible controller", class) == 0 ||
|
||||
strcasecmp("3D controller", class) == 0 ||
|
||||
strcasecmp("Display controller", class) == 0
|
||||
) {
|
||||
FFGPUResult* result = ffListAdd(&results);
|
||||
|
||||
ffStrbufInitA(&result->vendor, 256);
|
||||
ffpci_lookup_name(pacc, result->vendor.chars, (int) result->vendor.allocated -1, PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->vendor);
|
||||
|
||||
ffStrbufInitA(&result->name, 256);
|
||||
ffpci_lookup_name(pacc, result->name.chars, (int) result->name.allocated - 1, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->name);
|
||||
|
||||
ffStrbufInit(&result->driver);
|
||||
if(instance->config.gpuFormat.length > 0) //We only need it for the format string, so don't detect it if it isn't needed
|
||||
pciGetDriver(dev, &result->driver, ffpci_get_param);
|
||||
};
|
||||
}
|
||||
|
||||
ffpci_cleanup(pacc);
|
||||
dlclose(pci);
|
||||
|
||||
if(results.length == 0)
|
||||
{
|
||||
ffListDestroy(&results);
|
||||
return false;
|
||||
}
|
||||
|
||||
printGPUList(instance, &results);
|
||||
|
||||
ffListDestroy(&results);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool vulkanPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
const FFVulkanResult* result = ffDetectVulkan(instance);
|
||||
if(result->devices.length == 0)
|
||||
return false;
|
||||
|
||||
printGPUList(instance, &result->devices);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffPrintGPU(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FFlist gpus;
|
||||
ffListInitA(&gpus, sizeof(GPUResult), 4);
|
||||
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
pciFillGPUs(instance, &gpus);
|
||||
if(pciPrintGPUs(instance))
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
if(gpus.length == 0)
|
||||
vulkanFillGPUs(instance, &gpus);
|
||||
#endif
|
||||
if(vulkanPrintGPUs(instance))
|
||||
return;
|
||||
|
||||
for(uint8_t i = 0; i < (uint8_t) gpus.length; i++)
|
||||
printGPUResult(instance, gpus.length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(&gpus, i));
|
||||
|
||||
if(gpus.length == 0)
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, "No GPUs found.");
|
||||
|
||||
ffCacheClose(&cache);
|
||||
ffListDestroy(&gpus);
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpuKey, &instance->config.gpuFormat, FF_GPU_NUM_FORMAT_ARGS, "No GPUs found.");
|
||||
}
|
||||
|
||||
+12
-2
@@ -28,10 +28,20 @@ void ffPrintLocale(FFinstance* instance)
|
||||
FFstrbuf locale;
|
||||
ffStrbufInit(&locale);
|
||||
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/locale.conf", "LANG =", &locale);
|
||||
//Ubuntu (and deriviates) use a non standard locale file.
|
||||
//Parse it first, because on distributions where it exists, it takes precedence.
|
||||
//Otherwise use the standard /etc/locale.conf file.
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/default/locale", "LANG =", &locale);
|
||||
|
||||
if (locale.length == 0)
|
||||
if(locale.length == 0)
|
||||
{
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/locale.conf", "LANG =", &locale);
|
||||
}
|
||||
|
||||
if(locale.length == 0)
|
||||
{
|
||||
getLocaleFromEnv(&locale);
|
||||
}
|
||||
|
||||
if(locale.length == 0)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_OPENCL_MODULE_NAME "OpenCL"
|
||||
#define FF_OPENCL_NUM_FORMAT_ARGS 3
|
||||
|
||||
#ifdef FF_HAVE_OPENCL
|
||||
#define CL_TARGET_OPENCL_VERSION 100
|
||||
#include <CL/cl.h>
|
||||
|
||||
typedef struct OpenCLData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(clGetPlatformIDs);
|
||||
FF_LIBRARY_SYMBOL(clGetDeviceIDs);
|
||||
FF_LIBRARY_SYMBOL(clGetDeviceInfo);
|
||||
} OpenCLData;
|
||||
|
||||
static const char* openCLHandelData(FFinstance* instance, OpenCLData* data)
|
||||
{
|
||||
cl_platform_id platformID;
|
||||
cl_uint numPlatforms;
|
||||
data->ffclGetPlatformIDs(1, &platformID, &numPlatforms);
|
||||
|
||||
if(numPlatforms == 0)
|
||||
return "clGetPlatformIDs returned 0 platforms";
|
||||
|
||||
cl_device_id deviceID;
|
||||
cl_uint numDevices;
|
||||
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices);
|
||||
|
||||
if(numDevices == 0)
|
||||
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 1, &deviceID, &numDevices);
|
||||
|
||||
if(numDevices == 0)
|
||||
return "clGetDeviceIDs returned 0 devices";
|
||||
|
||||
char version[64];
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL);
|
||||
if(!ffStrSet(version))
|
||||
return "clGetDeviceInfo returned NULL or empty string";
|
||||
|
||||
char device[128];
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(device), device, NULL);
|
||||
|
||||
char vendor[32];
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL);
|
||||
|
||||
if(instance->config.openCLFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCLKey);
|
||||
puts(version);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCLKey, &instance->config.openCLFormat, NULL, FF_OPENCL_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRING, version},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, device},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, vendor}
|
||||
});
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* printOpenCL(FFinstance* instance)
|
||||
{
|
||||
OpenCLData data;
|
||||
|
||||
FF_LIBRARY_LOAD(opencl, instance->config.libOpenCL, "dlopen libOpenCL.so failed", "libOpenCL.so", 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(opencl, data.ffclGetPlatformIDs, clGetPlatformIDs, "dlsym clGetPlatformIDs failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(opencl, data.ffclGetDeviceIDs, clGetDeviceIDs, "dlsym clGetDeviceIDs failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(opencl, data.ffclGetDeviceInfo, clGetDeviceInfo, "dlsym clGetDeviceInfo failed");
|
||||
|
||||
const char* error = openCLHandelData(instance, &data);
|
||||
dlclose(opencl);
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffPrintOpenCL(FFinstance* instance)
|
||||
{
|
||||
const char* error;
|
||||
|
||||
#ifdef FF_HAVE_OPENCL
|
||||
error = printOpenCL(instance);
|
||||
#else
|
||||
error = "Fastfetch was build without OpenCL support";
|
||||
#endif
|
||||
|
||||
if(error != NULL)
|
||||
ffPrintError(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCLKey, &instance->config.openCLFormat, FF_OPENCL_NUM_FORMAT_ARGS, error);
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define FF_OPENGL_MODULE_NAME "OpenGL"
|
||||
#define FF_OPENGL_NUM_FORMAT_ARGS 4
|
||||
|
||||
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
|
||||
#define FF_HAVE_GL 1
|
||||
#include <GL/gl.h>
|
||||
|
||||
#define FF_OPENGL_BUFFER_WIDTH 1
|
||||
#define FF_OPENGL_BUFFER_HEIGHT 1
|
||||
|
||||
typedef struct GLData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(glGetString);
|
||||
} GLData;
|
||||
|
||||
static const char* glHandlePrint(FFinstance* instance, const GLData* data)
|
||||
{
|
||||
const char* version = (const char*) data->ffglGetString(GL_VERSION);
|
||||
if(!ffStrSet(version))
|
||||
return "glGetString(GL_VERSION) returned NULL";
|
||||
|
||||
const char* renderer = (const char*) data->ffglGetString(GL_RENDERER);
|
||||
const char* vendor = (const char*) data->ffglGetString(GL_VENDOR);
|
||||
const char* slv = (const char*) data->ffglGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
|
||||
if(instance->config.openGLFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_OPENGL_MODULE_NAME, 0, &instance->config.openGLKey);
|
||||
puts(version);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_OPENGL_MODULE_NAME, 0, &instance->config.openGLKey, &instance->config.openGLFormat, NULL, FF_OPENGL_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRING, version},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, renderer},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, slv}
|
||||
});
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
#include <EGL/egl.h>
|
||||
|
||||
typedef struct EGLData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(eglGetProcAddress);
|
||||
FF_LIBRARY_SYMBOL(eglGetDisplay);
|
||||
FF_LIBRARY_SYMBOL(eglInitialize);
|
||||
FF_LIBRARY_SYMBOL(eglBindAPI);
|
||||
FF_LIBRARY_SYMBOL(eglGetConfigs);
|
||||
FF_LIBRARY_SYMBOL(eglCreatePbufferSurface);
|
||||
FF_LIBRARY_SYMBOL(eglCreateContext);
|
||||
FF_LIBRARY_SYMBOL(eglMakeCurrent);
|
||||
FF_LIBRARY_SYMBOL(eglDestroyContext);
|
||||
FF_LIBRARY_SYMBOL(eglDestroySurface);
|
||||
FF_LIBRARY_SYMBOL(eglTerminate);
|
||||
|
||||
EGLDisplay display;
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
} EGLData;
|
||||
|
||||
static const char* eglHandleContext(FFinstance* instance, EGLData* data)
|
||||
{
|
||||
if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE)
|
||||
return "eglMakeCurrent returned EGL_FALSE";
|
||||
|
||||
return glHandlePrint(instance, &data->glData);
|
||||
}
|
||||
|
||||
static const char* eglHandleSurface(FFinstance* instance, EGLData* data)
|
||||
{
|
||||
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
|
||||
if(data->context == EGL_NO_CONTEXT)
|
||||
return "eglCreateContext returned EGL_NO_CONTEXT";
|
||||
|
||||
const char* error = eglHandleContext(instance, data);
|
||||
data->ffeglDestroyContext(data->display, data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleDisplay(FFinstance* instance, EGLData* data)
|
||||
{
|
||||
if(data->ffeglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
|
||||
return "eglBindAPI returned EGL_FALSE";
|
||||
|
||||
EGLint eglConfigCount;
|
||||
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
|
||||
if(eglConfigCount == 0)
|
||||
return "eglGetConfigs returned 0 configs";
|
||||
|
||||
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
|
||||
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
|
||||
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
if(data->surface == EGL_NO_SURFACE)
|
||||
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
|
||||
|
||||
const char* error = eglHandleSurface(instance, data);
|
||||
data->ffeglDestroySurface(data->display, data->surface);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleData(FFinstance* instance, EGLData* data)
|
||||
{
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffeglGetProcAddress("glGetString");
|
||||
if(!data->glData.ffglGetString)
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(data->display == EGL_NO_DISPLAY)
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
|
||||
EGLint major, minor;
|
||||
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
|
||||
return "eglInitialize returned EGL_FALSE";
|
||||
|
||||
const char* error = eglHandleDisplay(instance, data);
|
||||
data->ffeglTerminate(data->display);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglPrint(FFinstance* instance)
|
||||
{
|
||||
EGLData eglData;
|
||||
|
||||
FF_LIBRARY_LOAD(egl, instance->config.libEGL, "dlopen egl failed", "libEGL.so", 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglGetProcAddress, eglGetProcAddress, "dlsym eglGetProcAddress failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglGetDisplay, eglGetDisplay, "dlsym eglGetDisplay failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglInitialize, eglInitialize, "dlsym eglInitialize failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglBindAPI, eglBindAPI, "dlsym eglBindAPI failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglGetConfigs, eglGetConfigs, "dlsym eglGetConfigs failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglCreatePbufferSurface, eglCreatePbufferSurface, "dlsym eglCreatePbufferSurface failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglCreateContext, eglCreateContext, "dlsym eglCreateContext failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglMakeCurrent, eglMakeCurrent, "dlsym eglMakeCurrent failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglDestroyContext, eglDestroyContext, "dlsym eglDestroyContext failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglDestroySurface, eglDestroySurface, "dlsym eglDestroySurface failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(egl, eglData.ffeglTerminate, eglTerminate, "dlsym eglTerminate failed");
|
||||
|
||||
const char* error = eglHandleData(instance, &eglData);
|
||||
dlclose(egl);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_EGL
|
||||
|
||||
#ifdef FF_HAVE_GLX
|
||||
#include <GL/glx.h>
|
||||
|
||||
typedef struct GLXData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(glXGetProcAddress);
|
||||
FF_LIBRARY_SYMBOL(XOpenDisplay);
|
||||
FF_LIBRARY_SYMBOL(glXChooseVisual);
|
||||
FF_LIBRARY_SYMBOL(XCreatePixmap);
|
||||
FF_LIBRARY_SYMBOL(glXCreateGLXPixmap);
|
||||
FF_LIBRARY_SYMBOL(glXCreateContext);
|
||||
FF_LIBRARY_SYMBOL(glXMakeCurrent);
|
||||
FF_LIBRARY_SYMBOL(glXDestroyContext);
|
||||
FF_LIBRARY_SYMBOL(glXDestroyGLXPixmap);
|
||||
FF_LIBRARY_SYMBOL(XFreePixmap);
|
||||
FF_LIBRARY_SYMBOL(XCloseDisplay);
|
||||
|
||||
Display* display;
|
||||
XVisualInfo* visualInfo;
|
||||
Pixmap pixmap;
|
||||
GLXPixmap glxPixmap;
|
||||
GLXContext context;
|
||||
} GLXData;
|
||||
|
||||
static const char* glxHandleContext(FFinstance* instance, GLXData* data)
|
||||
{
|
||||
if(data->ffglXMakeCurrent(data->display, data->glxPixmap, data->context) != True)
|
||||
return "glXMakeCurrent returned False";
|
||||
|
||||
return glHandlePrint(instance, &data->glData);
|
||||
}
|
||||
|
||||
static const char* glxHandleGLXPixmap(FFinstance* instance, GLXData* data)
|
||||
{
|
||||
data->context = data->ffglXCreateContext(data->display, data->visualInfo, NULL, True);
|
||||
if(data->context == NULL)
|
||||
return "glXCreateContext returned NULL";
|
||||
|
||||
const char* error = glxHandleContext(instance, data);
|
||||
data->ffglXDestroyContext(data->display, data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxHandlePixmap(FFinstance* instance, GLXData* data)
|
||||
{
|
||||
data->glxPixmap = data->ffglXCreateGLXPixmap(data->display, data->visualInfo, data->pixmap);
|
||||
if(data->glxPixmap == None)
|
||||
return "glXCreateGLXPixmap returned None";
|
||||
|
||||
const char* error = glxHandleGLXPixmap(instance, data);
|
||||
data->ffglXDestroyGLXPixmap(data->display, data->glxPixmap);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxHandleVisualInfo(FFinstance* instance, GLXData* data)
|
||||
{
|
||||
data->pixmap = data->ffXCreatePixmap(data->display, DefaultRootWindow(data->display), FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, (unsigned int) data->visualInfo->depth);
|
||||
if(data->pixmap == None)
|
||||
return "XCreatePixmap returned None";
|
||||
|
||||
const char* error = glxHandlePixmap(instance, data);
|
||||
data->ffXFreePixmap(data->display, data->pixmap);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxHandleDisplay(FFinstance* instance, GLXData* data)
|
||||
{
|
||||
data->visualInfo = data->ffglXChooseVisual(data->display, DefaultScreen(data->display), (int[]){None});
|
||||
if(data->visualInfo == NULL)
|
||||
return "glXChooseVisual returned NULL";
|
||||
|
||||
return glxHandleVisualInfo(instance, data);
|
||||
}
|
||||
|
||||
static const char* glxHandleData(FFinstance* instance, GLXData* data)
|
||||
{
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
|
||||
if(data->glData.ffglGetString == NULL)
|
||||
return "glXGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffXOpenDisplay(NULL);
|
||||
if(data->display == NULL)
|
||||
return "XOpenDisplay returned NULL";
|
||||
|
||||
const char* error = glxHandleDisplay(instance, data);
|
||||
data->ffXCloseDisplay(data->display);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxPrint(FFinstance* instance)
|
||||
{
|
||||
GLXData data;
|
||||
|
||||
FF_LIBRARY_LOAD(glx, instance->config.libGLX, "dlopen glx failed", "libGLX.so", 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXGetProcAddress, glXGetProcAddress, "dlsym glXGetProcAddress failed");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXOpenDisplay, XOpenDisplay, "dlsym XOpenDisplay returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXChooseVisual, glXChooseVisual, "dlsym glXChooseVisual returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXCreatePixmap, XCreatePixmap, "dlsym XCreatePixmap returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXCreateGLXPixmap, glXCreateGLXPixmap, "dlsym glXCreateGLXPixmap returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXCreateContext, glXCreateContext, "dlsym glXCreateContext returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXMakeCurrent, glXMakeCurrent, "dlsym glXMakeCurrent returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXDestroyContext, glXDestroyContext, "dlsym glXDestroyContext returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffglXDestroyGLXPixmap, glXDestroyGLXPixmap, "dlsym glXDestroyGLXPixmap returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXFreePixmap, XFreePixmap, "dlsym XFreePixmap returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(glx, data.ffXCloseDisplay, XCloseDisplay, "dlsym XCloseDisplay returned NULL");
|
||||
|
||||
const char* error = glxHandleData(instance, &data);
|
||||
dlclose(glx);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_GLX
|
||||
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
#include <GL/osmesa.h>
|
||||
|
||||
typedef struct OSMesaData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(OSMesaGetProcAddress);
|
||||
FF_LIBRARY_SYMBOL(OSMesaCreateContext);
|
||||
FF_LIBRARY_SYMBOL(OSMesaMakeCurrent);
|
||||
FF_LIBRARY_SYMBOL(OSMesaDestroyContext);
|
||||
|
||||
OSMesaContext context;
|
||||
} OSMesaData;
|
||||
|
||||
static const char* osMesaHandleContext(FFinstance* instance, OSMesaData* data)
|
||||
{
|
||||
unsigned char buffer[FF_OPENGL_BUFFER_WIDTH * FF_OPENGL_BUFFER_HEIGHT * sizeof(uint32_t)]; // 4 bytes per pixel (RGBA)
|
||||
|
||||
if(data->ffOSMesaMakeCurrent(data->context, buffer, GL_UNSIGNED_BYTE, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT) != GL_TRUE)
|
||||
return "OSMesaMakeCurrent returned GL_FALSE";
|
||||
|
||||
return glHandlePrint(instance, &data->glData);
|
||||
}
|
||||
|
||||
static const char* osMesaHandleData(FFinstance* instance, OSMesaData* data)
|
||||
{
|
||||
//The case to void* is required here, because OSMESAproc can't be cast to (__typeof__(data->glData.ffglGetString)) without a warning, even though it is the actual type.
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) (void*) data->ffOSMesaGetProcAddress("glGetString");
|
||||
if(data->glData.ffglGetString == NULL)
|
||||
return "OSMesaGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->context = data->ffOSMesaCreateContext(OSMESA_RGBA, NULL);
|
||||
if(data->context == NULL)
|
||||
return "OSMesaCreateContext returned NULL";
|
||||
|
||||
const char* error = osMesaHandleContext(instance, data);
|
||||
data->ffOSMesaDestroyContext(data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* osMesaPrint(FFinstance* instance)
|
||||
{
|
||||
OSMesaData data;
|
||||
|
||||
FF_LIBRARY_LOAD(osmesa, instance->config.libOSMesa, "dlopen osmesa failed", "libOSMesa.so", 8);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaGetProcAddress, OSMesaGetProcAddress, "dlsym OSMesaGetProcAddress returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaCreateContext, OSMesaCreateContext, "dlsym OSMesaCreateContext returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaMakeCurrent, OSMesaMakeCurrent, "dlsym OSMesaMakeCurrent returned NULL");
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(osmesa, data.ffOSMesaDestroyContext, OSMesaDestroyContext, "dlsym OSMesaDestroyContext returned NULL");
|
||||
|
||||
const char* error = osMesaHandleData(instance, &data);
|
||||
dlclose(osmesa);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_OSMESA
|
||||
|
||||
static const char* glPrint(FFinstance* instance)
|
||||
{
|
||||
if(instance->config.glType == FF_GL_TYPE_GLX)
|
||||
{
|
||||
#ifdef FF_HAVE_GLX
|
||||
return glxPrint(instance);
|
||||
#else
|
||||
return "fastfetch was compiled without glx support";
|
||||
#endif
|
||||
}
|
||||
|
||||
if(instance->config.glType == FF_GL_TYPE_EGL)
|
||||
{
|
||||
#ifdef FF_HAVE_EGL
|
||||
return eglPrint(instance);
|
||||
#else
|
||||
return "fastfetch was compiled without egl support";
|
||||
#endif
|
||||
}
|
||||
|
||||
if(instance->config.glType == FF_GL_TYPE_OSMESA)
|
||||
{
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
return osMesaPrint(instance);
|
||||
#else
|
||||
return "fastfetch was compiled without osmesa support";
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* error = ""; // not NULL dummy value
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
error = eglPrint(instance);
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_GLX
|
||||
if(error != NULL)
|
||||
error = glxPrint(instance);
|
||||
#endif
|
||||
|
||||
//We don't use osmesa in auto mode here, because it is a software implementation,
|
||||
//that doesn't reflect the opengl supported by the hardware
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_GL
|
||||
|
||||
void ffPrintOpenGL(FFinstance* instance)
|
||||
{
|
||||
const char* error;
|
||||
|
||||
#ifndef FF_HAVE_GL
|
||||
error = "Fastfetch was built without gl support.";
|
||||
#else
|
||||
error = glPrint(instance);
|
||||
#endif
|
||||
|
||||
if(error != NULL)
|
||||
ffPrintError(instance, FF_OPENGL_MODULE_NAME, 0, &instance->config.openGLKey, &instance->config.openGLFormat, FF_OPENGL_NUM_FORMAT_ARGS, error);
|
||||
}
|
||||
+22
-17
@@ -5,9 +5,6 @@
|
||||
|
||||
void ffPrintOS(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_OS_MODULE_NAME, &instance->config.osKey, &instance->config.osFormat, FF_OS_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
const FFOSResult* result = ffDetectOS(instance);
|
||||
|
||||
if(result->name.length == 0 && result->prettyName.length == 0)
|
||||
@@ -69,20 +66,28 @@ void ffPrintOS(FFinstance* instance)
|
||||
ffStrbufAppendC(&os, ']');
|
||||
}
|
||||
|
||||
ffPrintAndWriteToCache(instance, FF_OS_MODULE_NAME, &instance->config.osKey, &os, &instance->config.osFormat, FF_OS_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->systemName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->id},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->idLike},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variant},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variantID},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->versionID},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->codename},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->buildID},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->architecture}
|
||||
});
|
||||
if(instance->config.osFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_OS_MODULE_NAME, 0, &instance->config.osKey);
|
||||
ffStrbufPutTo(&os, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_OS_MODULE_NAME, 0, &instance->config.osKey, &instance->config.osFormat, NULL, FF_OS_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->systemName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->id},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->idLike},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variant},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->variantID},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->versionID},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->codename},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->buildID},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->architecture}
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&os);
|
||||
}
|
||||
|
||||
+181
-138
@@ -4,59 +4,21 @@
|
||||
#include <dirent.h>
|
||||
|
||||
#define FF_PACKAGES_MODULE_NAME "Packages"
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 9
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 11
|
||||
|
||||
#ifdef FF_HAVE_RPM
|
||||
#include <rpm/rpmlib.h>
|
||||
#include <rpm/rpmts.h>
|
||||
#include <rpm/rpmdb.h>
|
||||
#include <rpm/rpmlog.h>
|
||||
|
||||
static uint32_t getRpmFromLibrpm(const FFinstance* instance)
|
||||
typedef struct PackageCounts
|
||||
{
|
||||
FF_LIBRARY_LOAD(rpm, instance->config.librpm, 0, "librpm.so", 12)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
|
||||
uint32_t pacman;
|
||||
uint32_t dpkg;
|
||||
uint32_t rpm;
|
||||
uint32_t emerge;
|
||||
uint32_t xbps;
|
||||
uint32_t nixDefault;
|
||||
uint32_t flatpak;
|
||||
uint32_t snap;
|
||||
|
||||
// Don't print any error messages
|
||||
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
|
||||
|
||||
if(ffrpmReadConfigFiles(NULL, NULL) != 0)
|
||||
{
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpmts ts = ffrpmtsCreate();
|
||||
if(ts == NULL)
|
||||
{
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0);
|
||||
if(mi == NULL)
|
||||
{
|
||||
ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = ffrpmdbGetIteratorCount(mi);
|
||||
|
||||
ffrpmdbFreeIterator(mi);
|
||||
ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
|
||||
return count > 0 ? (uint32_t) count : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
FFstrbuf pacmanBranch;
|
||||
} PackageCounts;
|
||||
|
||||
static uint32_t getNumElements(const char* dirname, unsigned char type)
|
||||
{
|
||||
@@ -140,25 +102,19 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDirPath, const char* filename)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t countFilesIn(const char* dirname, const char* filename)
|
||||
static uint32_t getNixPackages(char* path)
|
||||
{
|
||||
FFstrbuf baseDirPath;
|
||||
ffStrbufInitA(&baseDirPath, 128);
|
||||
ffStrbufAppendS(&baseDirPath, dirname);
|
||||
uint32_t result = countFilesRecursive(&baseDirPath, filename);
|
||||
ffStrbufDestroy(&baseDirPath);
|
||||
return result;
|
||||
}
|
||||
//Nix detection is kinda slow, so we only do it if the dir exists
|
||||
if(!ffFileExists(path, S_IFDIR))
|
||||
return 0;
|
||||
|
||||
static uint32_t getNixPackages(const FFstrbuf* path)
|
||||
{
|
||||
FFstrbuf output;
|
||||
ffStrbufInitA(&output, 128);
|
||||
|
||||
ffProcessAppendStdOut(&output, (char* const[]) {
|
||||
"nix-store",
|
||||
"-qR",
|
||||
path->chars,
|
||||
path,
|
||||
NULL
|
||||
});
|
||||
|
||||
@@ -171,105 +127,190 @@ static uint32_t getNixPackages(const FFstrbuf* path)
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t getNixPackagesDefault()
|
||||
#ifdef FF_HAVE_RPM
|
||||
#include <rpm/rpmlib.h>
|
||||
#include <rpm/rpmts.h>
|
||||
#include <rpm/rpmdb.h>
|
||||
#include <rpm/rpmlog.h>
|
||||
|
||||
static uint32_t getRpmFromLibrpm(const FFinstance* instance)
|
||||
{
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendS(&path, FASTFETCH_TARGET_DIR_ROOT"/nix/var/nix/profiles/default");
|
||||
uint32_t result = getNixPackages(&path);
|
||||
ffStrbufDestroy(&path);
|
||||
return result;
|
||||
FF_LIBRARY_LOAD(rpm, instance->config.librpm, 0, "librpm.so", 12)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
|
||||
|
||||
// Don't print any error messages
|
||||
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
|
||||
|
||||
if(ffrpmReadConfigFiles(NULL, NULL) != 0)
|
||||
{
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpmts ts = ffrpmtsCreate();
|
||||
if(ts == NULL)
|
||||
{
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0);
|
||||
if(mi == NULL)
|
||||
{
|
||||
ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = ffrpmdbGetIteratorCount(mi);
|
||||
|
||||
ffrpmdbFreeIterator(mi);
|
||||
ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
|
||||
return count > 0 ? (uint32_t) count : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
|
||||
{
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
//pacman
|
||||
ffStrbufAppendS(baseDir, "/var/lib/pacman/local");
|
||||
packageCounts->pacman += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//dpkg
|
||||
ffStrbufAppendS(baseDir, "/var/lib/dpkg/status");
|
||||
packageCounts->dpkg += getNumStrings(baseDir->chars, "Status: ");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//rpm
|
||||
ffStrbufAppendS(baseDir, "/var/lib/rpm/rmpdb.sqlite");
|
||||
packageCounts->rpm += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(blob) FROM Packages");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//emerge
|
||||
ffStrbufAppendS(baseDir, "/var/db/pkg");
|
||||
packageCounts->emerge += countFilesRecursive(baseDir, "SIZE");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//xps
|
||||
ffStrbufAppendS(baseDir, "/var/db/xbps");
|
||||
packageCounts->xbps += getNumElements(baseDir->chars, DT_REG);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//flatpak
|
||||
ffStrbufAppendS(baseDir, "/var/lib/flatpak/app");
|
||||
packageCounts->flatpak += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//nix default
|
||||
ffStrbufAppendS(baseDir, "/var/nix/profiles/default");
|
||||
packageCounts->nixDefault += getNixPackages(baseDir->chars);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//snap
|
||||
ffStrbufAppendS(baseDir, "/snap");
|
||||
uint32_t snap = getNumElements(baseDir->chars, DT_DIR);
|
||||
if(snap > 0)
|
||||
packageCounts->snap += (snap - 1); //Accounting for the /snap/bin folder
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//pacman branch
|
||||
ffStrbufAppendS(baseDir, "/etc/pacman-mirrors.conf");
|
||||
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
|
||||
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
static uint32_t getNixPackagesUser(const FFinstance* instance)
|
||||
static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
|
||||
{
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendS(&path, instance->state.passwd->pw_dir);
|
||||
ffStrbufAppendS(&path, "/.nix-profile");
|
||||
uint32_t result = getNixPackages(&path);
|
||||
ffStrbufDestroy(&path);
|
||||
return result;
|
||||
}
|
||||
ffStrbufAppendS(baseDir, "/bedrock/strata");
|
||||
|
||||
static uint32_t getRpmPackageCount(const FFinstance* instance)
|
||||
{
|
||||
// We do our own sql querys instead of using (lib)rpm, because:
|
||||
// - simply faster
|
||||
// - we don't need to regulary increase librpm version, which increases rapidly without providing a major version symlink
|
||||
uint32_t rpm = (uint32_t) ffSettingsGetSQLite3Int(instance, FASTFETCH_TARGET_DIR_ROOT"/var/lib/rpm/rpmdb.sqlite", "SELECT count(blob) FROM Packages");
|
||||
if(rpm != 0)
|
||||
return rpm;
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
return;
|
||||
|
||||
rpm = (uint32_t) ffSettingsGetSQLite3Int(instance, FASTFETCH_TARGET_DIR_ROOT"/var/cache/dnf/packages.db", "SELECT count(pkg) FROM installed");
|
||||
if(rpm != 0)
|
||||
return rpm;
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
|
||||
// If SQL failed, we can still try with rpm.
|
||||
// This is needed on openSUSE, which seems to use a proprietary database file
|
||||
#ifdef FF_HAVE_RPM
|
||||
return getRpmFromLibrpm(instance);
|
||||
#endif
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
return 0;
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
getPackageCounts(instance, baseDir, packageCounts);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void ffPrintPackages(FFinstance* instance)
|
||||
{
|
||||
uint32_t pacman = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/lib/pacman/local", DT_DIR);
|
||||
uint32_t dpkg = getNumStrings(FASTFETCH_TARGET_DIR_ROOT"/var/lib/dpkg/status", "Status: ");
|
||||
uint32_t rpm = getRpmPackageCount(instance);
|
||||
uint32_t emerge = countFilesIn(FASTFETCH_TARGET_DIR_ROOT"/var/db/pkg", "SIZE");
|
||||
uint32_t xbps = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/db/xbps", DT_REG);
|
||||
PackageCounts counts = {0};
|
||||
ffStrbufInit(&counts.pacmanBranch);
|
||||
|
||||
uint32_t nixUser = 0;
|
||||
uint32_t nixDefault = 0;
|
||||
FFstrbuf baseDir;
|
||||
ffStrbufInitA(&baseDir, 512);
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
|
||||
|
||||
//Nix detection is kinda slow, so we only do it if the nix dir exists
|
||||
if(ffFileExists(FASTFETCH_TARGET_DIR_ROOT"/nix", S_IFDIR))
|
||||
{
|
||||
nixUser = getNixPackagesUser(instance);
|
||||
nixDefault = getNixPackagesDefault();
|
||||
}
|
||||
if(ffStrbufIgnCaseCompS(&ffDetectOS(instance)->id, "bedrock") == 0)
|
||||
getPackageCountsBedrock(instance, &baseDir, &counts);
|
||||
else
|
||||
getPackageCounts(instance, &baseDir, &counts);
|
||||
|
||||
uint32_t flatpak = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/lib/flatpak/app", DT_DIR);
|
||||
uint32_t snap = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/snap", DT_DIR);
|
||||
// If SQL failed, we can still try with librpm.
|
||||
// This is needed on openSUSE, which seems to use a proprietary database file
|
||||
// This method doesn't work on bedrock, so we do it here.
|
||||
#ifdef FF_HAVE_RPM
|
||||
if(counts.rpm == 0)
|
||||
counts.rpm = getRpmFromLibrpm(instance);
|
||||
#endif
|
||||
|
||||
//Accounting for the /snap/bin folder
|
||||
if(snap > 0)
|
||||
--snap;
|
||||
//nix user
|
||||
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
|
||||
ffStrbufAppendS(&baseDir, "/.nix-profile");
|
||||
uint32_t nixUser = getNixPackages(baseDir.chars);
|
||||
|
||||
uint32_t all = pacman + dpkg + rpm + emerge + xbps + nixUser + nixDefault + flatpak + snap;
|
||||
ffStrbufDestroy(&baseDir);
|
||||
|
||||
uint32_t all = counts.dpkg + counts.emerge + counts.flatpak + counts.nixDefault + nixUser + counts.pacman + counts.rpm + counts.snap + counts.xbps;
|
||||
if(all == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packagesKey, &instance->config.packagesFormat, FF_PACKAGES_NUM_FORMAT_ARGS, "No packages from known package managers found");
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf manjaroBranch;
|
||||
ffStrbufInit(&manjaroBranch);
|
||||
if(ffParsePropFile(FASTFETCH_TARGET_DIR_ROOT"/etc/pacman-mirrors.conf", "Branch =", &manjaroBranch) && manjaroBranch.length == 0)
|
||||
ffStrbufSetS(&manjaroBranch, "stable");
|
||||
|
||||
if(instance->config.packagesFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packagesKey);
|
||||
|
||||
#define FF_PRINT_PACKAGE(name) \
|
||||
if(name > 0) \
|
||||
if(counts.name > 0) \
|
||||
{ \
|
||||
printf("%u ("#name")", name); \
|
||||
if((all = all - name) > 0) \
|
||||
printf("%u ("#name")", counts.name); \
|
||||
if((all = all - counts.name) > 0) \
|
||||
printf(", "); \
|
||||
};
|
||||
|
||||
if(pacman > 0)
|
||||
if(counts.pacman > 0)
|
||||
{
|
||||
printf("%u (pacman)", pacman);
|
||||
if(manjaroBranch.length > 0)
|
||||
printf("[%s]", manjaroBranch.chars);
|
||||
if((all = all - pacman) > 0)
|
||||
printf("%u (pacman)", counts.pacman);
|
||||
if(counts.pacmanBranch.length > 0)
|
||||
printf("[%s]", counts.pacmanBranch.chars);
|
||||
if((all = all - counts.pacman) > 0)
|
||||
printf(", ");
|
||||
};
|
||||
|
||||
@@ -284,10 +325,10 @@ void ffPrintPackages(FFinstance* instance)
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
if(nixDefault > 0)
|
||||
if(counts.nixDefault > 0)
|
||||
{
|
||||
printf("%u (nix-default)", nixDefault);
|
||||
if((all = all - nixDefault) > 0)
|
||||
printf("%u (nix-default)", counts.nixDefault);
|
||||
if((all = all - counts.nixDefault) > 0)
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
@@ -305,16 +346,18 @@ void ffPrintPackages(FFinstance* instance)
|
||||
{
|
||||
ffPrintFormatString(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packagesKey, &instance->config.packagesFormat, NULL, FF_PACKAGES_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &all},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &pacman},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &manjaroBranch},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &dpkg},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &rpm},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &emerge},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &xbps},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &flatpak},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &snap}
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.pacman},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &counts.pacmanBranch},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.dpkg},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.rpm},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.emerge},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.xbps},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &nixUser},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.nixDefault},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.flatpak},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.snap}
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&manjaroBranch);
|
||||
ffStrbufDestroy(&counts.pacmanBranch);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ void ffPrintSeparator(FFinstance* instance)
|
||||
const FFTitleResult* result = ffDetectTitle(instance);
|
||||
uint32_t titleLength = result->userName.length + 1 + result->hostname.length;
|
||||
|
||||
ffPrintLogoLine(instance);
|
||||
ffLogoPrintLine(instance);
|
||||
|
||||
if(instance->config.separatorString.length == 0)
|
||||
{
|
||||
|
||||
+10
-4
@@ -30,17 +30,23 @@ const FFTitleResult* ffDetectTitle(FFinstance* instance)
|
||||
|
||||
static inline void printTitlePart(FFinstance* instance, const FFstrbuf* content)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
ffPrintColor(&instance->config.mainColor);
|
||||
if(!instance->config.pipe)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
ffPrintColor(&instance->config.mainColor);
|
||||
}
|
||||
|
||||
ffStrbufWriteTo(content, stdout);
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(!instance->config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
}
|
||||
|
||||
void ffPrintTitle(FFinstance* instance)
|
||||
{
|
||||
const FFTitleResult* result = ffDetectTitle(instance);
|
||||
|
||||
ffPrintLogoLine(instance);
|
||||
ffLogoPrintLine(instance);
|
||||
|
||||
printTitlePart(instance, &result->userName);
|
||||
putchar('@');
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_VULKAN_MODULE_NAME "Vulkan"
|
||||
#define FF_VULKAN_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintVulkan(FFinstance* instance)
|
||||
{
|
||||
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
|
||||
|
||||
if(vulkan->apiVersion.length == 0 && vulkan->driver.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkanKey, &instance->config.vulkanFormat, FF_VULKAN_NUM_FORMAT_ARGS, "Failed to detect vulkan");
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->config.vulkanFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkanKey);
|
||||
|
||||
if(vulkan->driver.length > 0)
|
||||
{
|
||||
printf("%s (driver)", vulkan->driver.chars);
|
||||
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
fputs(", ", stdout);
|
||||
}
|
||||
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
printf("%s (api version)", vulkan->apiVersion.chars);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkanKey, &instance->config.vulkanFormat, NULL, FF_VULKAN_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->driver},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->apiVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vulkan->conformanceVersion}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user