mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
67 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 | |||
| 8c910089cc | |||
| e79af7ba79 | |||
| 960364bd47 | |||
| ea44231c78 | |||
| 60af0b9e39 | |||
| e4ecb9d069 | |||
| 3c648d84db | |||
| 45db4a5c3d | |||
| caf976bec2 | |||
| b3d855355e | |||
| 0a2eb49891 | |||
| ab2efa151a | |||
| 1aee3f81c5 | |||
| 4c7031cb12 | |||
| 81c96d0f11 | |||
| 4d8680ec2d | |||
| 039eb3a38a | |||
| d07a653404 | |||
| 76c0b7e457 | |||
| 1c0e532b79 | |||
| c79a9f1bff | |||
| 759069adfa | |||
| 66ff6adfb0 | |||
| 1dba19c49f | |||
| 2afd158d96 | |||
| 36c2ce6219 | |||
| 5f6432c150 | |||
| e9f0eca3dd | |||
| 998691847e | |||
| 64e5ef0df7 | |||
| cc1e876faf | |||
| 964a5aa8b4 | |||
| ad2601f097 | |||
| 7cae63ac05 | |||
| 0d26cfb218 | |||
| 3b6855b9da | |||
| 51414c5511 | |||
| 24f8ad7673 | |||
| e404dd62c0 | |||
| 21b315d548 | |||
| 14fa052257 | |||
| 5861012d95 | |||
| 4d9fbd93d2 |
@@ -7,6 +7,13 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# General description of bug:
|
||||
|
||||
|
||||
# Often helpful questions:
|
||||
* Does the issue occur across multiple terminal emulators? [Y/N]
|
||||
* Does the issue occur across multiple shells? (bash, zsh, fish, etc) [Y/N]
|
||||
|
||||
Output of `fastfetch --version`:
|
||||
```
|
||||
//paste here
|
||||
@@ -27,9 +34,8 @@ Output of `fastfetch --list-features`:
|
||||
//paste here
|
||||
```
|
||||
|
||||
<!--
|
||||
If you get the following error: `Error: couldn't find config: [...]`, copy the files in [presets](../../presets/) to `/usr/share/fastfetch/presets/` or `~/.local/share/fastfetch/presets/`.
|
||||
If this isn't possible (or to much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
|
||||
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
|
||||
-->
|
||||
|
||||
Often helpful questions:
|
||||
* Does the issue occur across multiple terminal emulators?
|
||||
* Does the issue occur across multiple shells? (bash, zsh, fish, etc)
|
||||
|
||||
@@ -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 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 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
|
||||
|
||||
+77
-2
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads
|
||||
|
||||
project(fastfetch
|
||||
VERSION 1.3.3
|
||||
VERSION 1.5.1
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
@@ -27,10 +27,16 @@ OPTION(ENABLE_GIO "Enable gio-2.0" ON)
|
||||
OPTION(ENABLE_DCONF "Enable dconf" ON)
|
||||
OPTION(ENABLE_DBUS "Enable dbus-1" ON)
|
||||
OPTION(ENABLE_XFCONF "Enable libxfconf-0" ON)
|
||||
OPTION(ENABLE_SQLITE3 "Enable sqlite3" ON)
|
||||
OPTION(ENABLE_RPM "Enable rpm" ON)
|
||||
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)
|
||||
@@ -121,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
|
||||
@@ -156,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
|
||||
@@ -164,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)
|
||||
@@ -265,12 +275,21 @@ if(ENABLE_XFCONF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_SQLITE3)
|
||||
pkg_check_modules(SQLITE3 sqlite3)
|
||||
if(SQLITE3_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_SQLITE3=1)
|
||||
else()
|
||||
message(WARNING "Package sqlite3 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_RPM)
|
||||
pkg_check_modules(RPM rpm)
|
||||
if(RPM_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_RPM=1)
|
||||
else()
|
||||
message(WARNING "Package librpm not found. Building without support.")
|
||||
message(WARNING "Package rpm not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -321,6 +340,55 @@ if(ENABLE_ZLIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_CHAFA)
|
||||
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 "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()
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
PUBLIC ${PROJECT_BINARY_DIR}
|
||||
PUBLIC ${PROJECT_SOURCE_DIR}/src
|
||||
@@ -336,10 +404,17 @@ target_include_directories(libfastfetch
|
||||
PRIVATE ${DCONF_INCLUDE_DIRS}
|
||||
PRIVATE ${DBUS_INCLUDE_DIRS}
|
||||
PRIVATE ${XFCONF_INCLUDE_DIRS}
|
||||
PRIVATE ${SQLITE3_INCLUDE_DIRS}
|
||||
PRIVATE ${RPM_INCLUDE_DIRS}
|
||||
PRIVATE ${IMAGEMAGICK7_INCLUDE_DIRS}
|
||||
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
|
||||
|
||||
@@ -11,11 +11,9 @@ Here i just add things that are easy to forget.
|
||||
- `libffdetect`: contains all the detection stuff. To be used by anything that needs system information
|
||||
- `libffprint`: contains the printing functions, logos, format etc
|
||||
- `fastfetch` and `flashfetch`: Executables, that initialize the config of libffprint. Fist one at runtime, second one at compile time
|
||||
- [ ] Support for printing images as ascii art logos (using imlib2 and libcaca probably)
|
||||
- [ ] 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,32 +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.
|
||||
* [`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.
|
||||
* [`librpm`](http://rpm.org/): Needed for rpm package count.
|
||||
* [`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, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, 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.
|
||||
|
||||
+16
-1
@@ -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=(
|
||||
@@ -231,9 +240,15 @@ __fastfetch_completion()
|
||||
"--lib-DConf"
|
||||
"--lib-DBus"
|
||||
"--lib-XFConf"
|
||||
"--lib-RPM"
|
||||
"--lib-sqlite3"
|
||||
"--lib-rpm"
|
||||
"--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);
|
||||
|
||||
+59
-21
@@ -108,7 +108,8 @@ static void defaultConfig(FFinstance* instance)
|
||||
instance->config.logoType = FF_LOGO_TYPE_AUTO;
|
||||
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
|
||||
ffStrbufInit(&instance->config.logoColors[i]);
|
||||
instance->config.logoWidth = 65;
|
||||
instance->config.logoWidth = 0;
|
||||
instance->config.logoHeight = 0; //preserve aspect ratio
|
||||
instance->config.logoPaddingLeft = 0;
|
||||
instance->config.logoPaddingRight = 4;
|
||||
instance->config.logoPrintRemaining = true;
|
||||
@@ -123,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);
|
||||
@@ -186,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);
|
||||
@@ -198,9 +208,15 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.libDConf, 0);
|
||||
ffStrbufInitA(&instance->config.libDBus, 0);
|
||||
ffStrbufInitA(&instance->config.libXFConf, 0);
|
||||
ffStrbufInitA(&instance->config.libSQLite3, 0);
|
||||
ffStrbufInitA(&instance->config.librpm, 0);
|
||||
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);
|
||||
|
||||
@@ -225,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;
|
||||
@@ -257,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
|
||||
@@ -317,14 +337,32 @@ void ffListFeatures()
|
||||
#ifdef FF_HAVE_IMAGEMAGICK6
|
||||
"imagemagick6\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_CHAFA
|
||||
"chafa\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
"zlib\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XFCONF
|
||||
"xfconf\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_SQLITE3
|
||||
"sqlite3\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_RPM
|
||||
"librpm\n"
|
||||
"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);
|
||||
|
||||
+25
-15
@@ -1,11 +1,11 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
|
||||
bool ffWriteFDContent(int fd, const FFstrbuf* content)
|
||||
{
|
||||
@@ -128,32 +128,42 @@ bool ffFileExists(const char* fileName, mode_t mode)
|
||||
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
|
||||
}
|
||||
|
||||
void ffGetTerminalResponse(const char* request, char end, const char* format, ...)
|
||||
void ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
{
|
||||
struct termios oldTerm, newTerm;
|
||||
tcgetattr(STDIN_FILENO, &oldTerm);
|
||||
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
|
||||
return;
|
||||
|
||||
newTerm = oldTerm;
|
||||
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newTerm);
|
||||
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
|
||||
return;
|
||||
|
||||
fputs(request, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
struct pollfd pfd;
|
||||
pfd.fd = STDIN_FILENO;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
//Give the terminal 35ms to respond
|
||||
if(poll(&pfd, 1, 35) <= 0)
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
int pos = 0;
|
||||
while((size_t) pos < sizeof(buffer) - 1)
|
||||
{
|
||||
char c = (char) getc(stdin);
|
||||
if(c == '\0')
|
||||
break;
|
||||
buffer[pos++] = c;
|
||||
if(c == end)
|
||||
break;
|
||||
}
|
||||
buffer[pos] = '\0';
|
||||
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
|
||||
if(readed <= 0)
|
||||
return;
|
||||
|
||||
buffer[readed] = '\0';
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsscanf(buffer, format, args);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
|
||||
static dataObject data; \
|
||||
@@ -267,6 +268,74 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
|
||||
}
|
||||
#endif //FF_HAVE_XFCONF
|
||||
|
||||
#ifdef FF_HAVE_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
|
||||
typedef struct SQLiteData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(sqlite3_open_v2)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_prepare_v2)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_step)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_data_count)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_column_int)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_finalize)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_close)
|
||||
} SQLiteData;
|
||||
|
||||
static const SQLiteData* getSQLiteData(const FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3.so", 1);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_step)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_data_count)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_int)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_finalize)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_close)
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_RETURN
|
||||
}
|
||||
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
|
||||
{
|
||||
const SQLiteData* data = getSQLiteData(instance);
|
||||
if(data == NULL)
|
||||
return 0;
|
||||
|
||||
sqlite3* db;
|
||||
if(data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
|
||||
return 0;
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
if(data->ffsqlite3_prepare_v2(db, query, (int) strlen(query), &stmt, NULL) != SQLITE_OK)
|
||||
{
|
||||
data->ffsqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(data->ffsqlite3_step(stmt) != SQLITE_ROW || data->ffsqlite3_data_count(stmt) < 1)
|
||||
{
|
||||
data->ffsqlite3_finalize(stmt);
|
||||
data->ffsqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int result = data->ffsqlite3_column_int(stmt, 0);
|
||||
|
||||
data->ffsqlite3_finalize(stmt);
|
||||
data->ffsqlite3_close(db);
|
||||
|
||||
return result;
|
||||
}
|
||||
#else //FF_HAVE_SQLITE3
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
|
||||
{
|
||||
FF_UNUSED(instance, dbPath, query)
|
||||
return 0;
|
||||
}
|
||||
#endif //FF_HAVE_SQLITE3
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/system_properties.h>
|
||||
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
|
||||
|
||||
+32
-2
@@ -61,16 +61,22 @@
|
||||
|
||||
# Logo type option:
|
||||
# Sets the logo type to use.
|
||||
# Must be auto, builtin, file, raw, sixel or kitty.
|
||||
# Must be auto, builtin, file, raw, sixel, kitty or chafa.
|
||||
# Default is auto.
|
||||
#--logo-type auto
|
||||
|
||||
# Logo width option:
|
||||
# Sets the width of the logos (in characters) if the logo is an image.
|
||||
# Sets the width of the logo (in characters) if the logo is an image.
|
||||
# Must be a positive integer.
|
||||
# Default is 65.
|
||||
#--logo-width 65
|
||||
|
||||
# Logo height option:
|
||||
# Sets the height of the logo (in characters) if the logo is an image.
|
||||
# Must be a positive integer.
|
||||
# Default is 0 (keeps aspect ration).
|
||||
#--logo-height 0
|
||||
|
||||
# Logo color options:
|
||||
# Overwrite a color in the logo. Also works for user provided logos.
|
||||
# In the user logo, they replace $[1-9]. Use $$ to print a single $ sign.
|
||||
@@ -145,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.
|
||||
@@ -177,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.
|
||||
@@ -212,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.
|
||||
@@ -227,6 +251,12 @@
|
||||
#--lib-DConf /usr/lib/libdconf.so
|
||||
#--lib-DBus /usr/lib/libdbus-1.so
|
||||
#--lib-XFConf /usr/lib/libxfconf-0.so
|
||||
#--lib-sqlite3 /usr/lib/libsqlite3.so
|
||||
#--lib-rpm /usr/lib/librpm.so
|
||||
#--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
|
||||
+19
-2
@@ -18,11 +18,14 @@ 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
|
||||
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel or kitty.
|
||||
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel, kitty or chafa.
|
||||
--logo-width <width>: set the width of the logo (in characters), if it is an image
|
||||
--logo-height <height>: set the height of the logo (in characters), if it is an image
|
||||
--logo-color-[1-9] <color>: overwrite a color in the logo
|
||||
--logo-padding <padding>: set the padding on the left and the right of the logo
|
||||
--logo-padding-left <padding>: set the padding on the left of the logo
|
||||
@@ -30,6 +33,7 @@ Logo options:
|
||||
--logo-print-remaining <?value>: weather to print the remaining logo, if it has more lines than modules to display
|
||||
--sixel <file>: short for --logo-type sixel --logo <file>
|
||||
--kitty <file>: short for --logo-type kitty --logo <file>
|
||||
--chafa <file>: short for --logo-type chafa --logo <file>
|
||||
--file <file>: short for --logo-type file --logo <file>
|
||||
--raw <file>: short for --logo-type raw --logo <file>
|
||||
|
||||
@@ -74,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>
|
||||
@@ -107,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>
|
||||
@@ -120,9 +130,15 @@ Library options: Set the path of a library to load
|
||||
--lib-DConf <path>
|
||||
--lib-DBus <path>
|
||||
--lib-XFConf <path>
|
||||
--lib-RPM <path>
|
||||
--lib-sqlite3 <path>
|
||||
--lib-rpm <path>
|
||||
--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
|
||||
@@ -134,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
|
||||
|
||||
@@ -98,7 +98,15 @@ static void getKDE(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "plasmashell");
|
||||
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
|
||||
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
|
||||
applyBetterWM(result, getenv("KDEWM"));
|
||||
}
|
||||
|
||||
@@ -289,13 +297,13 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
|
||||
|
||||
static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
DIR* proc = opendir(FASTFETCH_TARGET_DIR_ROOT"/proc");
|
||||
DIR* proc = opendir("/proc");
|
||||
if(proc == NULL)
|
||||
return;
|
||||
|
||||
FFstrbuf procPath;
|
||||
ffStrbufInitA(&procPath, 64);
|
||||
ffStrbufAppendS(&procPath, FASTFETCH_TARGET_DIR_ROOT"/proc/");
|
||||
ffStrbufAppendS(&procPath, "/proc/");
|
||||
|
||||
uint32_t procPathLength = procPath.length;
|
||||
|
||||
|
||||
@@ -213,15 +213,15 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
|
||||
return false;
|
||||
|
||||
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
|
||||
|
||||
free(crtcInfoReply);
|
||||
|
||||
return res ? true : ffdsAppendResolution(
|
||||
res = res ? true : ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
|
||||
free(crtcInfoReply);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output)
|
||||
|
||||
@@ -161,15 +161,15 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
|
||||
return false;
|
||||
|
||||
bool res = xrandrHandleMode(data, crtcInfo->mode);
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
|
||||
return res ? true : ffdsAppendResolution(
|
||||
res = res ? true : ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) crtcInfo->width,
|
||||
(uint32_t) crtcInfo->height,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool xrandrHandleOutput(XrandrData* data, RROutput output)
|
||||
|
||||
+17
-53
@@ -69,23 +69,14 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
|
||||
cursorTheme = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
}
|
||||
|
||||
//Fallback + Gnome impl
|
||||
|
||||
if(themeName == NULL)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0)
|
||||
{
|
||||
themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
|
||||
if(iconsName == NULL)
|
||||
iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
|
||||
if(fontName == NULL)
|
||||
fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
|
||||
if(cursorTheme == NULL)
|
||||
cursorTheme = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
|
||||
if(cursorSize <= 0)
|
||||
cursorSize = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
applyGTKDConfSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
|
||||
@@ -146,41 +137,8 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
|
||||
ffStrbufSubstrBefore(configDir, configDirLength);
|
||||
}
|
||||
|
||||
static void detectGTK(FFinstance* instance, const char* version, const char* envVariable, FFGTKResult* result)
|
||||
static void detectGTK(FFinstance* instance, const char* version, FFGTKResult* result)
|
||||
{
|
||||
FFstrbuf buffer;
|
||||
ffStrbufInitA(&buffer, 128);
|
||||
|
||||
// From ENV: GTK*_RC_FILES
|
||||
|
||||
ffStrbufSetS(&buffer, getenv(envVariable));
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < buffer.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&buffer, startIndex, ':');
|
||||
buffer.chars[colonIndex] = '\0';
|
||||
|
||||
detectGTKFromConfigFile(buffer.chars + startIndex, result);
|
||||
if(allPropertiesSet(result))
|
||||
{
|
||||
ffStrbufDestroy(&buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
//From DConf / GSettings
|
||||
|
||||
detectGTKFromDConf(instance, result);
|
||||
if(allPropertiesSet(result))
|
||||
{
|
||||
ffStrbufDestroy(&buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
//From config dirs
|
||||
|
||||
//We need to do this because we use multiple threads on configDirs
|
||||
FFstrbuf baseDirCopy;
|
||||
ffStrbufInitA(&baseDirCopy, 64);
|
||||
@@ -191,14 +149,20 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env
|
||||
ffStrbufSet(&baseDirCopy, baseDir);
|
||||
detectGTKFromConfigDir(&baseDirCopy, version, result);
|
||||
if(allPropertiesSet(result))
|
||||
break;
|
||||
{
|
||||
ffStrbufDestroy(&baseDirCopy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&baseDirCopy);
|
||||
ffStrbufDestroy(&buffer);
|
||||
|
||||
//Mate, Cinnamon and Gnome use dconf to save theme config
|
||||
//On other DEs, this will do nothing
|
||||
detectGTKFromDConf(instance, result);
|
||||
}
|
||||
|
||||
#define FF_CALCULATE_GTK_IMPL(version) \
|
||||
#define FF_DETECT_GTK_IMPL(version) \
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||
static FFGTKResult result; \
|
||||
static bool init = false; \
|
||||
@@ -213,23 +177,23 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env
|
||||
ffStrbufInit(&result.font); \
|
||||
ffStrbufInit(&result.cursor); \
|
||||
ffStrbufInit(&result.cursorSize); \
|
||||
detectGTK(instance, #version, "GTK"#version"_RC_FILES", &result); \
|
||||
detectGTK(instance, #version, &result); \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
return &result;
|
||||
|
||||
const FFGTKResult* ffDetectGTK2(FFinstance* instance)
|
||||
{
|
||||
FF_CALCULATE_GTK_IMPL(2)
|
||||
FF_DETECT_GTK_IMPL(2)
|
||||
}
|
||||
|
||||
const FFGTKResult* ffDetectGTK3(FFinstance* instance)
|
||||
{
|
||||
FF_CALCULATE_GTK_IMPL(3)
|
||||
FF_DETECT_GTK_IMPL(3)
|
||||
}
|
||||
|
||||
const FFGTKResult* ffDetectGTK4(FFinstance* instance)
|
||||
{
|
||||
FF_CALCULATE_GTK_IMPL(4)
|
||||
FF_DETECT_GTK_IMPL(4)
|
||||
}
|
||||
|
||||
#undef FF_CALCULATE_GTK_IMPL
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
|
||||
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
@@ -68,8 +69,11 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
|
||||
|
||||
while(true)
|
||||
{
|
||||
if((foundAValue = getValue(&subIter, result, data)))
|
||||
if(getValue(&subIter, result, data))
|
||||
{
|
||||
foundAValue = true;
|
||||
ffStrbufAppendS(result, ", ");
|
||||
}
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(subIter);
|
||||
}
|
||||
@@ -83,7 +87,7 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
|
||||
static DBusMessage* getReply(DBusMessage* request, DBusData* data)
|
||||
{
|
||||
DBusPendingCall* pendingCall = NULL;
|
||||
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, DBUS_TIMEOUT_USE_DEFAULT);
|
||||
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, FF_DBUS_TIMEOUT_MILLISECONDS);
|
||||
data->ffdbus_message_unref(request);
|
||||
if(!succesfull || pendingCall == NULL)
|
||||
return NULL;
|
||||
|
||||
+81
-4
@@ -1,15 +1,16 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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},
|
||||
@@ -26,6 +27,67 @@ static void parseFile(const char* fileName, FFOSResult* result)
|
||||
});
|
||||
}
|
||||
|
||||
static void getUbuntuFlavour(FFOSResult* result)
|
||||
{
|
||||
const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
|
||||
if(!ffStrSet(xdgConfigDirs))
|
||||
return;
|
||||
|
||||
if(strstr(xdgConfigDirs, "kde") != NULL || strstr(xdgConfigDirs, "plasma") != NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Kubuntu");
|
||||
ffStrbufSetS(&result->prettyName, "Kubuntu");
|
||||
ffStrbufSetS(&result->id, "kubuntu");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(strstr(xdgConfigDirs, "xfce") != NULL || strstr(xdgConfigDirs, "xubuntu") != NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Xubuntu");
|
||||
ffStrbufSetS(&result->prettyName, "Xubuntu");
|
||||
ffStrbufSetS(&result->id, "xubuntu");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(strstr(xdgConfigDirs, "lxde") != NULL || strstr(xdgConfigDirs, "lubuntu") != NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Lubuntu");
|
||||
ffStrbufSetS(&result->prettyName, "Lubuntu");
|
||||
ffStrbufSetS(&result->id, "lubuntu");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(strstr(xdgConfigDirs, "budgie") != NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Budgie");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Budgie");
|
||||
ffStrbufSetS(&result->id, "ubuntu-budgie");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(strstr(xdgConfigDirs, "mate") != NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu MATE");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu MATE");
|
||||
ffStrbufSetS(&result->id, "ubuntu-mate");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(strstr(xdgConfigDirs, "studio") != NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Studio");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Studio");
|
||||
ffStrbufSetS(&result->id, "ubuntu-studio");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const FFOSResult* ffDetectOS(const FFinstance* instance)
|
||||
@@ -62,12 +124,27 @@ 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);
|
||||
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", &result);
|
||||
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/lsb-release", &result);
|
||||
}
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&result.id, "ubuntu") == 0)
|
||||
getUbuntuFlavour(&result);
|
||||
|
||||
#else
|
||||
ffStrbufSetS(&result.name, "Android");
|
||||
ffStrbufSetS(&result.id, "android");
|
||||
|
||||
@@ -16,7 +16,7 @@ static void getProcessInformation(const char* pid, FFstrbuf* processName, FFstrb
|
||||
{
|
||||
FFstrbuf cmdlineFilePath;
|
||||
ffStrbufInit(&cmdlineFilePath);
|
||||
ffStrbufAppendS(&cmdlineFilePath, FASTFETCH_TARGET_DIR_ROOT"/proc/");
|
||||
ffStrbufAppendS(&cmdlineFilePath, "/proc/");
|
||||
ffStrbufAppendS(&cmdlineFilePath, pid);
|
||||
ffStrbufAppendS(&cmdlineFilePath, "/cmdline");
|
||||
|
||||
@@ -36,7 +36,7 @@ static void getTerminalShell(FFTerminalShellResult* result, const char* pid)
|
||||
{
|
||||
FFstrbuf statFilePath;
|
||||
ffStrbufInit(&statFilePath);
|
||||
ffStrbufAppendS(&statFilePath, FASTFETCH_TARGET_DIR_ROOT"/proc/");
|
||||
ffStrbufAppendS(&statFilePath, "/proc/");
|
||||
ffStrbufAppendS(&statFilePath, pid);
|
||||
ffStrbufAppendS(&statFilePath, "/stat");
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+105
-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)
|
||||
@@ -735,6 +775,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
instance->config.logoType = FF_LOGO_TYPE_SIXEL;
|
||||
else if(strcasecmp(value, "kitty") == 0)
|
||||
instance->config.logoType = FF_LOGO_TYPE_KITTY;
|
||||
else if(strcasecmp(value, "chafa") == 0)
|
||||
instance->config.logoType = FF_LOGO_TYPE_CHAFA;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: unknown logo type: %s\n", value);
|
||||
@@ -757,6 +799,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
}
|
||||
else if(strcasecmp(key, "--logo-width") == 0)
|
||||
instance->config.logoWidth = optionParseUInt32(key, value);
|
||||
else if(strcasecmp(key, "--logo-height") == 0)
|
||||
instance->config.logoHeight = optionParseUInt32(key, value);
|
||||
else if(strcasecmp(key, "--logo-padding") == 0)
|
||||
{
|
||||
uint32_t padding = optionParseUInt32(key, value);
|
||||
@@ -789,6 +833,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.logoSource);
|
||||
instance->config.logoType = FF_LOGO_TYPE_RAW;
|
||||
}
|
||||
else if(strcasecmp(key, "--chafa") == 0)
|
||||
{
|
||||
optionParseString(key, value, &instance->config.logoSource);
|
||||
instance->config.logoType = FF_LOGO_TYPE_CHAFA;
|
||||
}
|
||||
|
||||
///////////////////
|
||||
//Display options//
|
||||
@@ -955,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//
|
||||
@@ -982,12 +1043,24 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.libDBus);
|
||||
else if(strcasecmp(key, "--lib-XFConf") == 0)
|
||||
optionParseString(key, value, &instance->config.libXFConf);
|
||||
else if(strcasecmp(key, "--lib-sqlite") == 0 || strcasecmp(key, "--lib-sqlite3") == 0)
|
||||
optionParseString(key, value, &instance->config.libSQLite3);
|
||||
else if(strcasecmp(key, "--lib-rpm") == 0)
|
||||
optionParseString(key, value, &instance->config.librpm);
|
||||
else if(strcasecmp(key, "--lib-imagemagick") == 0)
|
||||
optionParseString(key, value, &instance->config.libImageMagick);
|
||||
else if(strcasecmp(key, "--lib-z") == 0)
|
||||
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//
|
||||
@@ -1011,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//
|
||||
@@ -1152,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>");
|
||||
}
|
||||
|
||||
+69
-11
@@ -38,20 +38,30 @@ typedef enum FFLogoType
|
||||
FF_LOGO_TYPE_FILE, //Raw text file, printed as is.
|
||||
FF_LOGO_TYPE_RAW, //Raw text file, printed with color codes replacement.
|
||||
FF_LOGO_TYPE_SIXEL, //Image file, printed as sixel codes.
|
||||
FF_LOGO_TYPE_KITTY //Image file, printed as kitty graphics protocol
|
||||
FF_LOGO_TYPE_KITTY, //Image file, printed as kitty graphics protocol
|
||||
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;
|
||||
FFLogoType logoType;
|
||||
FFstrbuf logoColors[FASTFETCH_LOGO_MAX_COLORS];
|
||||
uint32_t logoWidth;
|
||||
uint32_t logoHeight;
|
||||
uint32_t logoPaddingLeft;
|
||||
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;
|
||||
@@ -60,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;
|
||||
@@ -123,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;
|
||||
@@ -135,9 +154,15 @@ typedef struct FFconfig
|
||||
FFstrbuf libDConf;
|
||||
FFstrbuf libDBus;
|
||||
FFstrbuf libXFConf;
|
||||
FFstrbuf libSQLite3;
|
||||
FFstrbuf librpm;
|
||||
FFstrbuf libImageMagick;
|
||||
FFstrbuf libZ;
|
||||
FFstrbuf libChafa;
|
||||
FFstrbuf libEGL;
|
||||
FFstrbuf libGLX;
|
||||
FFstrbuf libOSMesa;
|
||||
FFstrbuf libOpenCL;
|
||||
|
||||
FFstrbuf diskFolders;
|
||||
|
||||
@@ -176,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;
|
||||
@@ -231,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;
|
||||
@@ -405,9 +453,10 @@ bool ffWriteFileContent(const char* fileName, const FFstrbuf* buffer);
|
||||
bool ffFileExists(const char* fileName, mode_t mode);
|
||||
void ffSuppressIO(bool suppress); // Not thread safe!
|
||||
|
||||
void ffGetTerminalResponse(const char* request, char end, const char* format, ...);
|
||||
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);
|
||||
@@ -448,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[]);
|
||||
|
||||
@@ -463,6 +515,8 @@ FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, c
|
||||
FFvariant ffSettingsGet(FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
|
||||
FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type);
|
||||
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
|
||||
#endif
|
||||
@@ -471,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 //
|
||||
@@ -511,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 //
|
||||
//////////////////////
|
||||
@@ -558,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);
|
||||
|
||||
|
||||
+211
-203
@@ -1,28 +1,15 @@
|
||||
#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("unkown", "question mark", "?")
|
||||
FF_LOGO_NAMES("unknown", "question mark", "?")
|
||||
FF_LOGO_LINES(
|
||||
" ________\n"
|
||||
" _jgN########Ngg_\n"
|
||||
@@ -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
|
||||
@@ -408,6 +425,82 @@ static const FFlogo* getLogoDebianSmall()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoDevuan()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("devuan", "devuan-linux")
|
||||
FF_LOGO_LINES(
|
||||
" ..,,;;;::;,..\n"
|
||||
" `':ddd;:,.\n"
|
||||
" `'dPPd:,.\n"
|
||||
" `:b$$b`.\n"
|
||||
" 'P$$$d`\n"
|
||||
" .$$$$$`\n"
|
||||
" ;$$$$$P\n"
|
||||
" .:P$$$$$$`\n"
|
||||
" .,:b$$$$$$$;'\n"
|
||||
" .,:dP$$$$$$$$b:'\n"
|
||||
" .,:;db$$$$$$$$$$Pd'`\n"
|
||||
" ,db$$$$$$$$$$$$$$b:'`\n"
|
||||
":$$$$$$$$$$$$b:'`\n"
|
||||
" `$$$$$bd:''`\n"
|
||||
" `'''`\n"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"35" //magenta
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoDevuanSmall()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("devuan_small", "devuan-linux-small")
|
||||
FF_LOGO_LINES(
|
||||
" ..:::.\n"
|
||||
" ..-==-\n"
|
||||
" .+#:\n"
|
||||
" =@@\n"
|
||||
" :+%@#:\n"
|
||||
".:=+#@@%*:\n"
|
||||
"#@@@#=:\n"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"34" //blue
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoDeepin()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("deepin", "deepin-linux")
|
||||
FF_LOGO_LINES(
|
||||
"$1 ............\n"
|
||||
" .';;;;;. .,;,.\n"
|
||||
" .,;;;;;;;. ';;;;;;;.\n"
|
||||
" .;::::::::' .,::;;,''''',.\n"
|
||||
" ,'.:::::::: .;;'. ';\n"
|
||||
" ;' 'cccccc, ,' :: '.. .:\n"
|
||||
" ,, :ccccc. ;: .c, '' :. ,;\n"
|
||||
".l. cllll' ., .lc :; .l' l.\n"
|
||||
".c :lllc ;cl: .l' .ll. :'\n"
|
||||
".l 'looc. . ,o: 'oo' c,\n"
|
||||
".o. .:ool::coc' .ooo' o.\n"
|
||||
" :: ..... .;dddo ;c\n"
|
||||
" l:... .';lddddo. ,o\n"
|
||||
" lxxxxxdoolllodxxxxxxxxxc :l\n"
|
||||
" ,dxxxxxxxxxxxxxxxxxxl. 'o,\n"
|
||||
" ,dkkkkkkkkkkkkko;. .;o;\n"
|
||||
" .;okkkkkdl;. .,cl:.\n"
|
||||
" .,:cccccccc:,."
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"32" //green
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoEndeavour()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -632,6 +725,39 @@ static const FFlogo* getLogoKDENeon()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoKubuntu()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("kubuntu", "kubuntu-linux", "kde-ubuntu", "ubuntu-kde", "ubuntu-plasma")
|
||||
FF_LOGO_LINES(
|
||||
"$1 `.:/ossyyyysso/:.\n"
|
||||
" .:oyyyyyyyyyyyyyyyyyyo:`\n"
|
||||
" -oyyyyyyyo$2dMMy$1yyyyyyysyyyyo-\n"
|
||||
" -syyyyyyyyyy$2dMMy$1oyyyy$2dmMMy$1yyyys-\n"
|
||||
" oyyys$2dMy$1syyyy$2dMMMMMMMMMMMMMy$1yyyyyyo\n"
|
||||
" `oyyyy$2dMMMMy$1syysoooooo$2dMMMMy$1yyyyyyyyo`\n"
|
||||
" oyyyyyy$2dMMMMy$1yyyyyyyyyyys$2dMMy$1sssssyyyo\n"
|
||||
"-yyyyyyyy$2dMy$1syyyyyyyyyyyyyys$2dMMMMMy$1syyy-\n"
|
||||
"oyyyysoo$2dMy$1yyyyyyyyyyyyyyyyyy$2dMMMMy$1syyyo\n"
|
||||
"yyys$2dMMMMMy$1yyyyyyyyyyyyyyyyyysosyyyyyyyy\n"
|
||||
"yyys$2dMMMMMy$1yyyyyyyyyyyyyyyyyyyyyyyyyyyyy\n"
|
||||
"oyyyyysos$2dy$1yyyyyyyyyyyyyyyyyy$2dMMMMy$1syyyo\n"
|
||||
"-yyyyyyyy$2dMy$1syyyyyyyyyyyyyys$2dMMMMMy$1syyy-\n"
|
||||
" oyyyyyy$2dMMMy$1syyyyyyyyyyys$2dMMy$1oyyyoyyyo\n"
|
||||
" `oyyyy$2dMMMy$1syyyoooooo$2dMMMMy$1oyyyyyyyyo\n"
|
||||
" oyyysyyoyyyys$2dMMMMMMMMMMMy$1yyyyyyyo\n"
|
||||
" -syyyyyyyyy$2dMMMy$1syyy$2dMMMy$1syyyys-\n"
|
||||
" -oyyyyyyy$2dMMy$1yyyyyysosyyyyo-\n"
|
||||
" ./oyyyyyyyyyyyyyyyyyyo/.\n"
|
||||
" `.:/oosyyyysso/:.`"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"34", //blue
|
||||
"37" //white
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoLinux()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1112,6 +1238,67 @@ static const FFlogo* getLogoRedHatEnterpriseLinux()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoRedstarOS()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("redstar", "redstar-os", "redstaros", "redstaros-linux", "redstar-os-linux")
|
||||
FF_LOGO_LINES(
|
||||
"$1 ..\n"
|
||||
" .oK0l\n"
|
||||
" :0KKKKd.\n"
|
||||
" .xKO0KKKKd\n"
|
||||
" ,Od' .d0000l\n"
|
||||
" .c;. .'''... ..'.\n"
|
||||
".,:cloddxxxkkkkOOOOkkkkkkkkxxxxxxxxxkkkx:\n"
|
||||
";kOOOOOOOkxOkc'...',;;;;,,,'',;;:cllc:,.\n"
|
||||
" .okkkkd,.lko .......',;:cllc:;,,'''''.\n"
|
||||
" .cdo. :xd' cd:. ..';'',,,'',,;;;,'.\n"
|
||||
" . .ddl.;doooc'..;oc;'..';::;,'.\n"
|
||||
" coo;.oooolllllllcccc:'. .\n"
|
||||
" .ool''lllllccccccc:::::;.\n"
|
||||
" ;lll. .':cccc:::::::;;;;'\n"
|
||||
" :lcc:'',..';::::;;;;;;;,,.\n"
|
||||
" :cccc::::;...';;;;;,,,,,,.\n"
|
||||
" ,::::::;;;,'. ..',,,,'''.\n"
|
||||
" ........ ......"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"31" //red
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoRockyLinux()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("rocky", "rocky-linux", "rockylinux")
|
||||
FF_LOGO_LINES(
|
||||
" __wgliliiligw_,\n"
|
||||
" _williiiiiiliilililw,\n"
|
||||
" _%iiiiiilililiiiiiiiiiii_\n"
|
||||
" .Qliiiililiiiiiiililililiilm.\n"
|
||||
" _iiiiiliiiiiililiiiiiiiiiiliil,\n"
|
||||
" .lililiiilililiiiilililililiiiii,\n"
|
||||
"_liiiiiiliiiiiiiliiiiiF{iiiiiilili,\n"
|
||||
"jliililiiilililiiili@` ~ililiiiiiL\n"
|
||||
"iiiliiiiliiiiiiili>` ~liililii\n"
|
||||
"liliiiliiilililii` -9liiiil\n"
|
||||
"iiiiiliiliiiiii~ ''4lili\n"
|
||||
"4ililiiiiilil~| -w, )4lf\n"
|
||||
"-liiiiililiF' _liig, )'\n"
|
||||
" )iiiliii@` _QIililig,\n"
|
||||
" )iiii>` .Qliliiiililw\n"
|
||||
" )<>~ .mliiiiiliiiiiil,\n"
|
||||
" _gllilililiililii~\n"
|
||||
" giliiiiiiiiiiiiT`\n"
|
||||
" -^~$ililili@~~'"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"32" //green
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoUbuntu()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1242,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,
|
||||
@@ -1256,12 +1441,16 @@ static GetLogoMethod* getLogos()
|
||||
getLogoArcoLinux,
|
||||
getLogoArtix,
|
||||
getLogoArtixSmall,
|
||||
getLogoBedrock,
|
||||
getLogoCachyOS,
|
||||
getLogoCelOS,
|
||||
getLogoCentOS,
|
||||
getLogoCentOSSmall,
|
||||
getLogoDebian,
|
||||
getLogoDevuan,
|
||||
getLogoDevuanSmall,
|
||||
getLogoDebianSmall,
|
||||
getLogoDeepin,
|
||||
getLogoEndeavour,
|
||||
getLogoFedora,
|
||||
getLogoFedoraSmall,
|
||||
@@ -1270,6 +1459,7 @@ static GetLogoMethod* getLogos()
|
||||
getLogoGentoo,
|
||||
getLogoGentooSmall,
|
||||
getLogoKDENeon,
|
||||
getLogoKubuntu,
|
||||
getLogoLinux,
|
||||
getLogoManjaro,
|
||||
getLogoManjaroSmall,
|
||||
@@ -1288,6 +1478,8 @@ static GetLogoMethod* getLogos()
|
||||
getLogoReborn,
|
||||
getLogoRebornSmall,
|
||||
getLogoRedHatEnterpriseLinux,
|
||||
getLogoRedstarOS,
|
||||
getLogoRockyLinux,
|
||||
getLogoUbuntu,
|
||||
getLogoUbuntuSmall,
|
||||
getLogoVoid,
|
||||
@@ -1298,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;
|
||||
}
|
||||
}
|
||||
|
||||
+252
-85
@@ -5,13 +5,16 @@
|
||||
#define FF_KITTY_MAX_CHUNK_SIZE 4096
|
||||
|
||||
#define FF_CACHE_FILE_HEIGHT "height"
|
||||
#define FF_CACHE_FILE_WIDTH "width"
|
||||
#define FF_CACHE_FILE_SIXEL "sixel"
|
||||
#define FF_CACHE_FILE_KITTY_COMPRESSED "kittyc"
|
||||
#define FF_CACHE_FILE_KITTY_UNCOMPRESSED "kittyu"
|
||||
#define FF_CACHE_FILE_CHAFA "chafa"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
#include <zlib.h>
|
||||
@@ -79,42 +82,54 @@ static inline bool checkAllocationResult(void* data, size_t length)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void finishPrinting(FFinstance* instance, const FFLogoRequestData* requestData)
|
||||
static inline uint32_t simpleCeil(double value)
|
||||
{
|
||||
instance->state.logoWidth = (uint32_t) (requestData->imagePixelWidth / requestData->characterPixelWidth) + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
|
||||
instance->state.logoHeight = (uint32_t) (requestData->imagePixelHeight / requestData->characterPixelHeight);
|
||||
|
||||
//Seems to be required on all consoles that support sixel. TBH i don't know why.
|
||||
if(requestData->type == FF_LOGO_TYPE_SIXEL)
|
||||
instance->state.logoHeight += 1;
|
||||
|
||||
fputs("\033[9999999D", stdout);
|
||||
printf("\033[%uA", instance->state.logoHeight);
|
||||
uint32_t result = (uint32_t) value;
|
||||
return value == (double) result ? result : result + 1;
|
||||
}
|
||||
|
||||
static void writeResult(FFinstance* instance, FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName)
|
||||
static void writeCacheStrbuf(FFLogoRequestData* requestData, const FFstrbuf* value, const char* cacheFileName)
|
||||
{
|
||||
uint32_t cacheDirLength = requestData->cacheDir.length;
|
||||
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
|
||||
ffWriteFileContent(requestData->cacheDir.chars, value);
|
||||
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
|
||||
}
|
||||
|
||||
static void writeCacheUint32(FFLogoRequestData* requestData, uint32_t value, const char* cacheFileName)
|
||||
{
|
||||
FFstrbuf content;
|
||||
content.chars = (char*) &value;
|
||||
content.length = sizeof(value);
|
||||
writeCacheStrbuf(requestData, &content, cacheFileName);
|
||||
}
|
||||
|
||||
static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName)
|
||||
{
|
||||
//Calculate character dimensions
|
||||
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
|
||||
|
||||
instance->state.logoHeight = requestData->logoCharacterHeight;
|
||||
if(requestData->type == FF_LOGO_TYPE_KITTY)
|
||||
instance->state.logoHeight -= 1;
|
||||
|
||||
//Write cache files
|
||||
writeCacheStrbuf(requestData, result, cacheFileName);
|
||||
|
||||
if(instance->config.logoWidth == 0)
|
||||
writeCacheUint32(requestData, instance->state.logoWidth, FF_CACHE_FILE_WIDTH);
|
||||
|
||||
if(instance->config.logoHeight == 0)
|
||||
writeCacheUint32(requestData, instance->state.logoHeight, FF_CACHE_FILE_HEIGHT);
|
||||
|
||||
//Write result to stdout
|
||||
ffPrintCharTimes(' ', instance->config.logoPaddingLeft);
|
||||
fflush(stdout);
|
||||
ffWriteFDContent(STDOUT_FILENO, result);
|
||||
|
||||
//Write result to cache file
|
||||
uint32_t cacheDirLength = requestData->cacheDir.length;
|
||||
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
|
||||
ffWriteFileContent(requestData->cacheDir.chars, result);
|
||||
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
|
||||
|
||||
//Write height cache file
|
||||
ffStrbufAppendS(&requestData->cacheDir, FF_CACHE_FILE_HEIGHT);
|
||||
FFstrbuf content;
|
||||
content.chars = (char*) &requestData->imagePixelHeight;
|
||||
content.length = sizeof(requestData->imagePixelHeight);
|
||||
ffWriteFileContent(requestData->cacheDir.chars, &content);
|
||||
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
|
||||
|
||||
//Write escape codes to stdout
|
||||
finishPrinting(instance, requestData);
|
||||
//Go to upper left corner
|
||||
fputs("\033[9999999D", stdout);
|
||||
printf("\033[%uA", instance->state.logoHeight);
|
||||
}
|
||||
|
||||
static bool printImageSixel(FFinstance* instance, FFLogoRequestData* requestData, const ImageData* imageData)
|
||||
@@ -130,7 +145,7 @@ static bool printImageSixel(FFinstance* instance, FFLogoRequestData* requestData
|
||||
result.chars = (char*) blob;
|
||||
result.length = (uint32_t) length;
|
||||
|
||||
writeResult(instance, requestData, &result, FF_CACHE_FILE_SIXEL);
|
||||
printImagePixels(instance, requestData, &result, FF_CACHE_FILE_SIXEL);
|
||||
|
||||
free(blob);
|
||||
return true;
|
||||
@@ -179,20 +194,79 @@ static bool printImageKitty(FFinstance* instance, FFLogoRequestData* requestData
|
||||
const char* currentPos = chars;
|
||||
size_t remainingLength = length;
|
||||
|
||||
ffStrbufAppendF(&result, "\033_Ga=T,f=32,s=%u,v=%u", requestData->imagePixelWidth, requestData->imagePixelHeight);
|
||||
ffStrbufAppendF(&result, "\033_Ga=T,f=32,s=%u,v=%u", requestData->logoPixelWidth, requestData->logoPixelHeight);
|
||||
if(isCompressed)
|
||||
ffStrbufAppendS(&result, ",o=z");
|
||||
appendKittyChunk(&result, ¤tPos, &remainingLength, false);
|
||||
while(remainingLength > 0)
|
||||
appendKittyChunk(&result, ¤tPos, &remainingLength, true);
|
||||
|
||||
writeResult(instance, requestData, &result, isCompressed ? FF_CACHE_FILE_KITTY_COMPRESSED : FF_CACHE_FILE_KITTY_UNCOMPRESSED);
|
||||
printImagePixels(instance, requestData, &result, isCompressed ? FF_CACHE_FILE_KITTY_COMPRESSED : FF_CACHE_FILE_KITTY_UNCOMPRESSED);
|
||||
|
||||
ffStrbufDestroy(&result);
|
||||
free(chars);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_CHAFA
|
||||
#include <chafa/chafa.h>
|
||||
static bool printImageChafa(FFinstance* instance, FFLogoRequestData* requestData, const ImageData* imageData)
|
||||
{
|
||||
FF_LIBRARY_LOAD(chafa, instance->config.libChafa, false, "libchafa.so", 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_new, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_add_by_tags, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_new, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_set_geometry, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_set_symbol_map, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_new, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_draw_all_pixels, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_print, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_unref, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_unref, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_unref, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(chafa, g_string_free, false)
|
||||
|
||||
imageData->ffCopyMagickString(imageData->imageInfo->magick, "RGBA", 5);
|
||||
size_t length;
|
||||
void* blob = imageData->ffImageToBlob(imageData->imageInfo, imageData->image, &length, imageData->exceptionInfo);
|
||||
if(!checkAllocationResult(blob, length))
|
||||
return false;
|
||||
|
||||
ChafaSymbolMap* symbolMap = ffchafa_symbol_map_new();
|
||||
ffchafa_symbol_map_add_by_tags(symbolMap, CHAFA_SYMBOL_TAG_ALL);
|
||||
|
||||
ChafaCanvasConfig* canvasConfig = ffchafa_canvas_config_new();
|
||||
ffchafa_canvas_config_set_geometry(canvasConfig, (gint) requestData->logoCharacterWidth, (gint) requestData->logoCharacterHeight);
|
||||
ffchafa_canvas_config_set_symbol_map(canvasConfig, symbolMap);
|
||||
|
||||
ChafaCanvas* canvas = ffchafa_canvas_new(canvasConfig);
|
||||
ffchafa_canvas_draw_all_pixels(
|
||||
canvas,
|
||||
CHAFA_PIXEL_RGBA8_UNASSOCIATED,
|
||||
blob,
|
||||
(gint) imageData->image->columns,
|
||||
(gint) imageData->image->rows,
|
||||
(gint) imageData->image->columns * 4
|
||||
);
|
||||
|
||||
GString* str = ffchafa_canvas_print(canvas, NULL);
|
||||
FFstrbuf result;
|
||||
result.allocated = (uint32_t) str->allocated_len;
|
||||
result.length = (uint32_t) str->len;
|
||||
result.chars = str->str;
|
||||
|
||||
ffLogoPrintChars(instance, result.chars, false);
|
||||
writeCacheStrbuf(requestData, &result, FF_CACHE_FILE_CHAFA);
|
||||
|
||||
ffg_string_free(str, TRUE);
|
||||
ffchafa_canvas_unref(canvas);
|
||||
ffchafa_canvas_config_unref(canvasConfig);
|
||||
ffchafa_symbol_map_unref(symbolMap);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData* requestData, const FFIMData* imData)
|
||||
{
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, AcquireExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
@@ -222,31 +296,43 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData*
|
||||
//+1, because we need to copy the null byte too
|
||||
imageData.ffCopyMagickString(imageInfoIn->filename, instance->config.logoSource.chars, instance->config.logoSource.length + 1);
|
||||
|
||||
Image* originalImage = ffReadImage(imageInfoIn, imageData.exceptionInfo);
|
||||
imageData.image = ffReadImage(imageInfoIn, imageData.exceptionInfo);
|
||||
ffDestroyImageInfo(imageInfoIn);
|
||||
if(originalImage == NULL)
|
||||
{
|
||||
ffDestroyExceptionInfo(imageData.exceptionInfo);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
}
|
||||
|
||||
//imagePixelWidth is set in ffLogoPrintImageIfExists
|
||||
requestData->imagePixelHeight = (uint32_t) ((requestData->imagePixelWidth / (double) originalImage->columns) * (double) originalImage->rows);
|
||||
if(requestData->imagePixelHeight < 1)
|
||||
{
|
||||
ffDestroyImage(originalImage);
|
||||
ffDestroyExceptionInfo(imageData.exceptionInfo);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
}
|
||||
|
||||
imageData.image = (Image*) imData->resizeFunc(originalImage, requestData->imagePixelWidth, requestData->imagePixelHeight, imageData.exceptionInfo);
|
||||
ffDestroyImage(originalImage);
|
||||
if(imageData.image == NULL)
|
||||
{
|
||||
ffDestroyExceptionInfo(imageData.exceptionInfo);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
}
|
||||
|
||||
if(requestData->logoPixelWidth == 0 && requestData->logoPixelHeight == 0)
|
||||
{
|
||||
requestData->logoPixelWidth = (uint32_t) imageData.image->columns;
|
||||
requestData->logoPixelHeight = (uint32_t) imageData.image->rows;
|
||||
}
|
||||
else if(requestData->logoPixelWidth == 0)
|
||||
requestData->logoPixelWidth = (uint32_t) ((double) imageData.image->columns / (double) imageData.image->rows * requestData->logoPixelHeight);
|
||||
else if(requestData->logoPixelHeight == 0)
|
||||
requestData->logoPixelHeight = (uint32_t) ((double) imageData.image->rows / (double) imageData.image->columns * requestData->logoPixelWidth);
|
||||
|
||||
requestData->logoCharacterWidth = simpleCeil((double) requestData->logoPixelWidth / requestData->characterPixelWidth);
|
||||
requestData->logoCharacterHeight = simpleCeil((double) requestData->logoPixelHeight / requestData->characterPixelHeight);
|
||||
|
||||
if(requestData->logoPixelWidth == 0 || requestData->logoPixelHeight == 0 || requestData->logoCharacterWidth == 0 || requestData->logoCharacterHeight == 0)
|
||||
{
|
||||
ffDestroyImage(imageData.image);
|
||||
ffDestroyExceptionInfo(imageData.exceptionInfo);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
}
|
||||
|
||||
Image* resized = imData->resizeFunc(imageData.image, requestData->logoPixelWidth, requestData->logoPixelHeight, imageData.exceptionInfo);
|
||||
ffDestroyImage(imageData.image);
|
||||
if(resized == NULL)
|
||||
{
|
||||
ffDestroyExceptionInfo(imageData.exceptionInfo);
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
}
|
||||
imageData.image = resized;
|
||||
|
||||
imageData.imageInfo = ffAcquireImageInfo();
|
||||
if(imageData.imageInfo == NULL)
|
||||
{
|
||||
@@ -255,10 +341,16 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData*
|
||||
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
|
||||
}
|
||||
|
||||
bool printSuccessful;
|
||||
if(requestData->type == FF_LOGO_TYPE_KITTY)
|
||||
bool printSuccessful = false;
|
||||
if(requestData->type == FF_LOGO_TYPE_CHAFA)
|
||||
{
|
||||
#ifdef FF_HAVE_CHAFA
|
||||
printSuccessful = printImageChafa(instance, requestData, &imageData);
|
||||
#endif
|
||||
}
|
||||
else if(requestData->type == FF_LOGO_TYPE_KITTY)
|
||||
printSuccessful = printImageKitty(instance, requestData, &imageData);
|
||||
else
|
||||
else if(requestData->type == FF_LOGO_TYPE_SIXEL)
|
||||
printSuccessful = printImageSixel(instance, requestData, &imageData);
|
||||
|
||||
ffDestroyImageInfo(imageData.imageInfo);
|
||||
@@ -277,32 +369,80 @@ static int getCacheFD(FFLogoRequestData* requestData, const char* fileName)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
|
||||
static void readCachedStrbuf(FFLogoRequestData* requestData, FFstrbuf* result, const char* cacheFileName)
|
||||
{
|
||||
uint32_t cacheDirLength = requestData->cacheDir.length;
|
||||
ffStrbufAppendS(&requestData->cacheDir, FF_CACHE_FILE_HEIGHT);
|
||||
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
|
||||
ffAppendFileContent(requestData->cacheDir.chars, result);
|
||||
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
|
||||
}
|
||||
|
||||
static uint32_t readCachedUint32(FFLogoRequestData* requestData, const char* cacheFileName)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInitA(&content, sizeof(requestData->imagePixelHeight) + 1); // +1 because strbuf is null terminated
|
||||
memset(content.chars, 0, sizeof(requestData->imagePixelHeight));
|
||||
ffStrbufInit(&content);
|
||||
readCachedStrbuf(requestData, &content, cacheFileName);
|
||||
|
||||
ffAppendFileContent(requestData->cacheDir.chars, &content);
|
||||
memcpy(&requestData->imagePixelHeight, content.chars, sizeof(requestData->imagePixelHeight));
|
||||
uint32_t result = 0;
|
||||
|
||||
if(content.length != sizeof(result))
|
||||
{
|
||||
ffStrbufDestroy(&content);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&result, content.chars, sizeof(result));
|
||||
|
||||
ffStrbufDestroy(&content);
|
||||
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
|
||||
|
||||
if(requestData->imagePixelHeight < 1)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool printCachedChars(FFinstance* instance, FFLogoRequestData* requestData)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInitA(&content, 32768);
|
||||
|
||||
if(requestData->type == FF_LOGO_TYPE_CHAFA)
|
||||
readCachedStrbuf(requestData, &content, FF_CACHE_FILE_CHAFA);
|
||||
|
||||
if(content.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&content);
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd;
|
||||
ffLogoPrintChars(instance, content.chars, false);
|
||||
ffStrbufDestroy(&content);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestData)
|
||||
{
|
||||
requestData->logoCharacterWidth = instance->config.logoWidth;
|
||||
if(requestData->logoCharacterWidth == 0)
|
||||
{
|
||||
requestData->logoCharacterWidth = readCachedUint32(requestData, FF_CACHE_FILE_WIDTH);
|
||||
if(requestData->logoCharacterWidth == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
requestData->logoCharacterHeight = instance->config.logoHeight;
|
||||
if(requestData->logoCharacterHeight == 0)
|
||||
{
|
||||
requestData->logoCharacterHeight = readCachedUint32(requestData, FF_CACHE_FILE_HEIGHT);
|
||||
if(requestData->logoCharacterHeight == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = -1;
|
||||
if(requestData->type == FF_LOGO_TYPE_KITTY)
|
||||
{
|
||||
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_COMPRESSED);
|
||||
if(fd == -1)
|
||||
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_UNCOMPRESSED);
|
||||
}
|
||||
else
|
||||
else if(requestData->type == FF_LOGO_TYPE_SIXEL)
|
||||
fd = getCacheFD(requestData, FF_CACHE_FILE_SIXEL);
|
||||
|
||||
if(fd == -1)
|
||||
@@ -314,48 +454,73 @@ static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
|
||||
char buffer[32768];
|
||||
ssize_t readBytes;
|
||||
while((readBytes = read(fd, buffer, sizeof(buffer))) > 0)
|
||||
(void) write(STDOUT_FILENO, buffer, (size_t) readBytes);
|
||||
FF_UNUSED(write(STDOUT_FILENO, buffer, (size_t) readBytes));
|
||||
|
||||
close(fd);
|
||||
|
||||
finishPrinting(instance, requestData);
|
||||
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
|
||||
instance->state.logoHeight = requestData->logoCharacterHeight;
|
||||
|
||||
//Go to upper left corner
|
||||
fputs("\033[9999999D", stdout);
|
||||
printf("\033[%uA", instance->state.logoHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getTermInfo(struct winsize* winsize)
|
||||
static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
|
||||
{
|
||||
if(requestData->type == FF_LOGO_TYPE_CHAFA)
|
||||
return printCachedChars(instance, requestData);
|
||||
else
|
||||
return printCachedPixel(instance, requestData);
|
||||
}
|
||||
|
||||
static bool getCharacterPixelDimensions(FFLogoRequestData* requestData)
|
||||
{
|
||||
struct winsize winsize;
|
||||
|
||||
//Initialize every member to 0, because it isn't guaranteed that every terminal sets them all
|
||||
memset(winsize, 0, sizeof(struct winsize));
|
||||
memset(&winsize, 0, sizeof(struct winsize));
|
||||
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, winsize);
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
|
||||
|
||||
if(winsize->ws_row == 0 || winsize->ws_col == 0)
|
||||
ffGetTerminalResponse("\033[18t", 't', "\033[8;%hu;%hut", &winsize->ws_row, &winsize->ws_col);
|
||||
if(winsize.ws_row == 0 || winsize.ws_col == 0)
|
||||
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
|
||||
|
||||
if(winsize->ws_ypixel == 0 || winsize->ws_xpixel == 0)
|
||||
ffGetTerminalResponse("\033[14t", 't', "\033[4;%hu;%hut", &winsize->ws_ypixel, &winsize->ws_xpixel);
|
||||
if(winsize.ws_row == 0 || winsize.ws_col == 0)
|
||||
return false;
|
||||
|
||||
return
|
||||
winsize->ws_row > 0 &&
|
||||
winsize->ws_col > 0 &&
|
||||
winsize->ws_ypixel > 0 &&
|
||||
winsize->ws_xpixel > 0;
|
||||
if(winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0)
|
||||
ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
|
||||
|
||||
requestData->characterPixelWidth = winsize.ws_xpixel / (double) winsize.ws_col;
|
||||
requestData->characterPixelHeight = winsize.ws_ypixel / (double) winsize.ws_row;
|
||||
|
||||
return requestData->characterPixelWidth > 1.0 && requestData->characterPixelHeight > 1.0;
|
||||
}
|
||||
|
||||
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
{
|
||||
//Performance optimisation
|
||||
#ifndef FF_HAVE_CHAFA
|
||||
if(type == FF_LOGO_TYPE_CHAFA)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
FFLogoRequestData requestData;
|
||||
|
||||
if(!getTermInfo(&requestData.winsize))
|
||||
return false;
|
||||
|
||||
requestData.type = type;
|
||||
requestData.characterPixelWidth = requestData.winsize.ws_xpixel / (double) requestData.winsize.ws_col;
|
||||
requestData.characterPixelHeight = requestData.winsize.ws_ypixel / (double) requestData.winsize.ws_row;
|
||||
requestData.imagePixelWidth = (uint32_t) (instance->config.logoWidth * requestData.characterPixelWidth);
|
||||
if(requestData.imagePixelWidth < 1)
|
||||
requestData.characterPixelWidth = 1;
|
||||
requestData.characterPixelHeight = 1;
|
||||
|
||||
if(
|
||||
(type != FF_LOGO_TYPE_CHAFA || instance->config.logoWidth == 0 || instance->config.logoHeight == 0) &&
|
||||
!getCharacterPixelDimensions(&requestData)
|
||||
)
|
||||
return false;
|
||||
|
||||
requestData.logoPixelWidth = simpleCeil((double) instance->config.logoWidth * requestData.characterPixelWidth);
|
||||
requestData.logoPixelHeight = simpleCeil((double) instance->config.logoHeight * requestData.characterPixelHeight);
|
||||
|
||||
ffStrbufInitA(&requestData.cacheDir, PATH_MAX * 2);
|
||||
ffStrbufAppend(&requestData.cacheDir, &instance->state.cacheDir);
|
||||
ffStrbufAppendS(&requestData.cacheDir, "images");
|
||||
@@ -371,7 +536,9 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
if(!ffStrbufEndsWithC(&requestData.cacheDir, '/'))
|
||||
ffStrbufAppendC(&requestData.cacheDir, '/');
|
||||
|
||||
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.imagePixelWidth);
|
||||
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.logoPixelWidth);
|
||||
ffStrbufAppendC(&requestData.cacheDir, '*');
|
||||
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.logoPixelHeight);
|
||||
ffStrbufAppendC(&requestData.cacheDir, '/');
|
||||
|
||||
if(!instance->config.recache && printCached(instance, &requestData))
|
||||
@@ -396,7 +563,7 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
}
|
||||
|
||||
#else //FF_HAVE_IMAGEMAGICK{6, 7}
|
||||
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
|
||||
{
|
||||
FF_UNUSED(instance, type);
|
||||
return false;
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
#ifndef FF_INCLUDED_LOGO_SIXEL_sixel
|
||||
#define FF_INCLUDED_LOGO_SIXEL_sixel
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "../logo.h"
|
||||
|
||||
#if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6)
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define MAGICKCORE_HDRI_ENABLE 1
|
||||
#define MAGICKCORE_QUANTUM_DEPTH 16
|
||||
|
||||
@@ -24,11 +22,14 @@ typedef struct FFLogoRequestData
|
||||
FFLogoType type;
|
||||
FFstrbuf cacheDir;
|
||||
|
||||
struct winsize winsize;
|
||||
double characterPixelWidth;
|
||||
double characterPixelHeight;
|
||||
uint32_t imagePixelWidth;
|
||||
uint32_t imagePixelHeight;
|
||||
|
||||
uint32_t logoPixelWidth;
|
||||
uint32_t logoPixelHeight;
|
||||
|
||||
uint32_t logoCharacterHeight;
|
||||
uint32_t logoCharacterWidth;
|
||||
} FFLogoRequestData;
|
||||
|
||||
typedef struct FFIMData
|
||||
@@ -50,5 +51,4 @@ FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoRequestData* r
|
||||
FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoRequestData* requestData);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+230
-73
@@ -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,112 +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);
|
||||
}
|
||||
|
||||
static void logoPrintDetected(FFinstance* instance)
|
||||
{
|
||||
if(instance->config.logoSource.length > 0)
|
||||
if(!ffAppendFileContent(instance->config.logoSource.chars, &content))
|
||||
{
|
||||
if(
|
||||
!ffLogoPrintBuiltinIfExists(instance) &&
|
||||
!ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_KITTY)
|
||||
) logoPrintFile(instance, true);
|
||||
return;
|
||||
ffStrbufDestroy(&content);
|
||||
return false;
|
||||
}
|
||||
|
||||
ffLogoPrintBuiltinDetected(instance);
|
||||
logoApplyMainColorDetected(instance);
|
||||
ffLogoPrintChars(instance, content.chars, doColorReplacement);
|
||||
ffStrbufDestroy(&content);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffPrintLogo(FFinstance* instance)
|
||||
static bool logoPrintImageIfExists(FFinstance* instance, FFLogoType logoType)
|
||||
{
|
||||
if(instance->config.mainColor.length == 0)
|
||||
ffLogoSetMainColor(instance);
|
||||
if(!ffLogoPrintImageIfExists(instance, logoType))
|
||||
return false;
|
||||
|
||||
if(( //Logo type needs set logo name, but nothing was given. Print question mark
|
||||
instance->config.logoType == FF_LOGO_TYPE_BUILTIN ||
|
||||
instance->config.logoType == FF_LOGO_TYPE_FILE ||
|
||||
instance->config.logoType == FF_LOGO_TYPE_RAW ||
|
||||
instance->config.logoType == FF_LOGO_TYPE_SIXEL
|
||||
) && instance->config.logoSource.length == 0)
|
||||
ffLogoPrintUnknown(instance);
|
||||
else if(instance->config.logoType == FF_LOGO_TYPE_BUILTIN)
|
||||
{
|
||||
if(!ffLogoPrintBuiltinIfExists(instance))
|
||||
ffLogoPrintUnknown(instance);
|
||||
}
|
||||
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)
|
||||
logoPrintFile(instance, true);
|
||||
successfull = logoPrintFileIfExists(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)
|
||||
{
|
||||
if(!ffLogoPrintImageIfExists(instance, instance->config.logoType))
|
||||
ffLogoPrintBuiltinDetected(instance);
|
||||
}
|
||||
else
|
||||
successfull = logoPrintFileIfExists(instance, false);
|
||||
else //image
|
||||
successfull = logoPrintImageIfExists(instance, instance->config.logoType);
|
||||
|
||||
if(!successfull)
|
||||
logoPrintDetected(instance);
|
||||
}
|
||||
|
||||
static inline void printLogoWidth(const FFinstance* 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)
|
||||
{
|
||||
instance->state.logoHeight = 0;
|
||||
instance->state.logoWidth = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//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);
|
||||
|
||||
//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;
|
||||
|
||||
//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;
|
||||
|
||||
//Try to load the logo as a file. If it succeeds, print it and return.
|
||||
if(logoPrintFileIfExists(instance, true))
|
||||
return;
|
||||
|
||||
logoPrintDetected(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
-7
@@ -5,17 +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);
|
||||
const FFlogo* ffLogoBuiltinGetUnknown();
|
||||
GetLogoMethod* ffLogoBuiltinGetAll();
|
||||
|
||||
void ffLogoPrintUnknown(FFinstance* instance);
|
||||
bool ffLogoPrintBuiltinIfExists(FFinstance* instance);
|
||||
void ffLogoPrintBuiltinDetected(FFinstance* instance);
|
||||
|
||||
//sixel/image.c
|
||||
//image/image.c
|
||||
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
|
||||
|
||||
+2
-2
@@ -39,10 +39,10 @@ void ffPrintCPU(FFinstance* instance)
|
||||
if(ffPrintFromCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpuKey, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FILE* cpuinfo = fopen(FASTFETCH_TARGET_DIR_ROOT"/proc/cpuinfo", "r");
|
||||
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if(cpuinfo == NULL)
|
||||
{
|
||||
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpuKey, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS, "fopen(\""FASTFETCH_TARGET_DIR_ROOT"/proc/cpuinfo\", \"r\") == NULL");
|
||||
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpuKey, &instance->config.cpuFormat, FF_CPU_NUM_FORMAT_ARGS, "fopen(\"""/proc/cpuinfo\", \"r\") == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
void ffPrintCPUUsage(FFinstance* instance)
|
||||
{
|
||||
long user, nice, system, idle, iowait, irq, softirq;
|
||||
FILE* procStat = fopen(FASTFETCH_TARGET_DIR_ROOT"/proc/stat", "r");
|
||||
FILE* procStat = fopen("/proc/stat", "r");
|
||||
if(procStat == NULL)
|
||||
{
|
||||
ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsageKey, &instance->config.cpuUsageFormat, FF_CPU_USAGE_NUM_FORMAT_ARGS, "fopen(\""FASTFETCH_TARGET_DIR_ROOT"/proc/stat\", \"r\") == NULL");
|
||||
ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsageKey, &instance->config.cpuUsageFormat, FF_CPU_USAGE_NUM_FORMAT_ARGS, "fopen(\"""/proc/stat\", \"r\") == NULL");
|
||||
return;
|
||||
}
|
||||
if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) goto exit;
|
||||
|
||||
+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)
|
||||
{
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
// Impl inspired by: https://github.com/sam-barr/paleofetch/blob/b7c58a52c0de39b53c9b5f417889a5886d324bfa/paleofetch.c#L544
|
||||
void ffPrintMemory(FFinstance* instance)
|
||||
{
|
||||
FILE* meminfo = fopen(FASTFETCH_TARGET_DIR_ROOT"/proc/meminfo", "r");
|
||||
FILE* meminfo = fopen("/proc/meminfo", "r");
|
||||
if(meminfo == NULL) {
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, FF_MEMORY_NUM_FORMAT_ARGS, "fopen(\""FASTFETCH_TARGET_DIR_ROOT"/proc/meminfo\", \"r\") == NULL");
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, FF_MEMORY_NUM_FORMAT_ARGS, "fopen(\"""/proc/meminfo\", \"r\") == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ void ffPrintMemory(FFinstance* instance)
|
||||
|
||||
if(used_mem == 0 && total_mem == 0 && percentage == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, FF_MEMORY_NUM_FORMAT_ARGS, FASTFETCH_TARGET_DIR_ROOT"/proc/meminfo could't be parsed");
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memoryKey, &instance->config.memoryFormat, FF_MEMORY_NUM_FORMAT_ARGS, "/proc/meminfo could't be parsed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+185
-112
@@ -4,45 +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 getRpmPackageCount(FFinstance* instance)
|
||||
typedef struct PackageCounts
|
||||
{
|
||||
FF_LIBRARY_LOAD(rpm, instance->config.librpm, 0, "librpm.so", 5)
|
||||
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));
|
||||
|
||||
uint32_t count = 0;
|
||||
rpmts ts = NULL;
|
||||
rpmdbMatchIterator mi = NULL;
|
||||
|
||||
if (ffrpmReadConfigFiles(NULL, NULL)) goto exit;
|
||||
if (!(ts = ffrpmtsCreate())) goto exit;
|
||||
if (!(mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0))) goto exit;
|
||||
count = (uint32_t) ffrpmdbGetIteratorCount(mi);
|
||||
|
||||
exit:
|
||||
if (mi) ffrpmdbFreeIterator(mi);
|
||||
if (ts) ffrpmtsFree(ts);
|
||||
dlclose(rpm);
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
FFstrbuf pacmanBranch;
|
||||
} PackageCounts;
|
||||
|
||||
static uint32_t getNumElements(const char* dirname, unsigned char type)
|
||||
{
|
||||
@@ -126,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
|
||||
});
|
||||
|
||||
@@ -157,89 +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");
|
||||
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
return;
|
||||
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
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: ");
|
||||
PackageCounts counts = {0};
|
||||
ffStrbufInit(&counts.pacmanBranch);
|
||||
|
||||
FFstrbuf baseDir;
|
||||
ffStrbufInitA(&baseDir, 512);
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&ffDetectOS(instance)->id, "bedrock") == 0)
|
||||
getPackageCountsBedrock(instance, &baseDir, &counts);
|
||||
else
|
||||
getPackageCounts(instance, &baseDir, &counts);
|
||||
|
||||
// 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
|
||||
uint32_t rpm = getRpmPackageCount(instance);
|
||||
#else
|
||||
uint32_t rpm = 0;
|
||||
if(counts.rpm == 0)
|
||||
counts.rpm = getRpmFromLibrpm(instance);
|
||||
#endif
|
||||
|
||||
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);
|
||||
//nix user
|
||||
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
|
||||
ffStrbufAppendS(&baseDir, "/.nix-profile");
|
||||
uint32_t nixUser = getNixPackages(baseDir.chars);
|
||||
|
||||
uint32_t nixUser = 0;
|
||||
uint32_t nixDefault = 0;
|
||||
|
||||
//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();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
//Accounting for the /snap/bin folder
|
||||
if(snap > 0)
|
||||
--snap;
|
||||
|
||||
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(", ");
|
||||
};
|
||||
|
||||
@@ -254,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(", ");
|
||||
}
|
||||
|
||||
@@ -275,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('@');
|
||||
|
||||
+34
-8
@@ -17,17 +17,43 @@ void ffPrintUptime(FFinstance* instance)
|
||||
if(days == 0 && hours == 0 && minutes == 0)
|
||||
{
|
||||
printf("%u seconds\n", seconds);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if(days > 0)
|
||||
{
|
||||
if(days > 0)
|
||||
printf("%u day%s%s, ", days, days <= 1 ? "" : "s", days < 100 ? "" : "(!)");
|
||||
if(hours > 0)
|
||||
printf("%u hour%s, ", hours, hours <= 1 ? "" : "s");
|
||||
if(minutes > 0)
|
||||
printf("%u min%s", minutes, minutes <= 1 ? "" : "s");
|
||||
putchar('\n');
|
||||
printf("%u day", days);
|
||||
|
||||
if(days > 1)
|
||||
putchar('s');
|
||||
|
||||
if(days >= 100)
|
||||
fputs("(!)", stdout);
|
||||
|
||||
if(hours > 0 || minutes > 0)
|
||||
fputs(", ", stdout);
|
||||
}
|
||||
|
||||
if(hours > 0)
|
||||
{
|
||||
printf("%u hour", hours);
|
||||
|
||||
if(hours > 1)
|
||||
putchar('s');
|
||||
|
||||
if(minutes > 0)
|
||||
fputs(", ", stdout);
|
||||
}
|
||||
|
||||
if(minutes > 0)
|
||||
{
|
||||
printf("%u min", minutes);
|
||||
|
||||
if(minutes > 1)
|
||||
putchar('s');
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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