Compare commits

...

25 Commits

Author SHA1 Message Date
Linus Dierheimer ccf4e2d2b5 OpenSUSE logos 2022-03-28 12:36:08 +02:00
Linus Dierheimer f2998a329d Add license info to rpm package 2022-03-25 12:24:56 +01:00
Linus Dierheimer 30365e8997 Release prebuild binaries as tar.gz and zip 2022-03-25 12:16:06 +01:00
Linus Dierheimer 5b66938bf4 Release with rpm package too 2022-03-25 12:09:48 +01:00
Linus Dierheimer 80c5600a7b Use cmake to build packages 2022-03-25 11:57:58 +01:00
Linus Dierheimer 65ce2eafed Hopefully finally fix github actions 2022-03-24 22:26:44 +01:00
Linus Dierheimer d840c7a12d Use workflow instead of action 2022-03-24 22:15:46 +01:00
Linus Dierheimer 634e27bc42 Try to give github actions the right permissions 2022-03-24 22:02:39 +01:00
Linus Dierheimer cc18315e84 Fix check action 2022-03-24 21:59:15 +01:00
Linus Dierheimer 83e2787b24 Use reusable action for check 2022-03-24 21:57:53 +01:00
Linus Dierheimer ef5a9384da Try to fix github actions again 2022-03-24 21:49:39 +01:00
Linus Dierheimer 2d7e6c37ff Try to fix github actions 2022-03-24 21:43:27 +01:00
Linus Dierheimer 92e8f23261 Refactored github actions again 2022-03-24 21:38:56 +01:00
Linus Dierheimer e09f1d3647 Refactored github actions 2022-03-24 21:32:45 +01:00
Linus Dierheimer 6f01e33955 Clear URL from unsucessfull media detection too 2022-03-24 19:06:20 +01:00
Linus Dierheimer 4b813cdf59 Automatic track commits between versions 2022-03-24 18:56:44 +01:00
Linus Dierheimer 942c583c89 Media: Don't show website urls 2022-03-23 21:41:52 +01:00
Linus Dierheimer 24a48c1fc0 Dont show lyric information in song title 2022-03-23 16:07:47 +01:00
Linus Dierheimer e2e95732e8 Don't remove dirty / clean from song title 2022-03-23 15:58:30 +01:00
Linus Dierheimer d647f9e3f2 Pretty song output, if the media is a browser playing a video 2022-03-23 15:43:30 +01:00
Linus Dierheimer 4895c68ca9 Capitalize the first letter of media player if appropiate 2022-03-23 11:54:05 +01:00
Linus Dierheimer f0b9800974 Fix fastfetch recaching every time if an old cache exists 2022-03-23 11:38:42 +01:00
Linus Dierheimer be84549f4c Refactored media detection 2022-03-23 11:15:50 +01:00
Linus Dierheimer 0916258c87 Greatly improved detection of media player name 2022-03-22 18:59:04 +01:00
Linus Dierheimer ad006b466c Version output include extra info 2022-03-20 17:12:52 +01:00
16 changed files with 477 additions and 201 deletions
+37
View File
@@ -0,0 +1,37 @@
name: manage pull requests
on: pull_request
jobs:
check:
name: manage pull request
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: checkout repository
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 libxfconf-0-dev rpm librpm-dev libzstd-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
- name: configure project
run: cmake -DBUILD_TESTS=On .
- name: build project
run: cmake --build . -j$(nproc) --target package
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true
- name: run flashfetch
run: ./flashfetch
- name: run tests
run: ctest
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v1
+28 -69
View File
@@ -1,101 +1,60 @@
name: Manage pushes and pull requests
name: manage pushes
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
BUILD_TYPE: Release
jobs:
check:
name: Build, Run and Analyze fastfetch
manage:
name: manage push
runs-on: ubuntu-latest
permissions:
actions: read
contents: write
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: checkout repository
uses: actions/checkout@v2
- name: Update and install 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 libxfconf-0-dev librpm-dev libzstd-dev
- 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 libxfconf-0-dev rpm librpm-dev libzstd-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
- name: Configure
run: cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .
- name: configure project
# We reuse the build binary only for the releases.
# We set tweak version to off, because it is wrong, as git tag will happen after this step. Releases don't have a tweak, so this is ok.
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: Build
run: cmake --build . -j$(nproc)
- name: build project
run: cmake --build . -j$(nproc) --target package
- name: Run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true
- name: Run flashfetch
run: ./flashfetch
- name: run flashfetch
run: ./flashfetch
- name: Run tests
run: ctest
- name: run tests
run: ctest
- name: Build deb package
run: sh packaging/deb/create.sh .
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Create tarball
if: github.event_name == 'push'
run: tar -cvf fastfetch.tar ./fastfetch -C packaging/deb ./fastfetch.deb
- name: Upload tarball
if: github.event_name == 'push'
uses: actions/upload-artifact@v3
with:
name: fastfetch.tar
path: ./fastfetch.tar
deploy:
name: Create GitHub release
runs-on: ubuntu-latest
needs: check
if: github.event_name == 'push'
permissions:
contents: write
steps:
- name: Download tarball
uses: actions/download-artifact@v3
with:
name: fastfetch.tar
path: ./fastfetch.tar
- name: Extract tarball
run: tar --overwrite -xvf ./fastfetch.tar/fastfetch.tar
- name: Get fastfetch version
- name: get fastfetch version
id: get_version_fastfetch
run: echo "::set-output name=release::$(./fastfetch --version)"
run: echo "::set-output name=release::$(./fastfetch --version-raw)"
- name: Get latest release version
- name: get latest release version
id: get_version_release
uses: pozetroninc/github-action-get-latest-release@master
with:
repository: ${{ github.repository }}
- name: Push release
- name: create release
if: steps.get_version_fastfetch.outputs.release != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ steps.get_version_fastfetch.outputs.release }}
commit: ${{ github.sha }}
artifacts: ./fastfetch,./fastfetch.deb
artifacts: ./fastfetch-*.*
-3
View File
@@ -1,3 +0,0 @@
[submodule "packaging/aur"]
path = packaging/aur
url = https://aur.archlinux.org/fastfetch-git.git
+55 -6
View File
@@ -1,11 +1,15 @@
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads
project(fastfetch
VERSION 1.0.0
VERSION 1.2.3
LANGUAGES C
)
include(GNUInstallDirs)
# This is set to off by github actions for release builds
OPTION(SET_TWEAK "Add tweak to project version" ON)
# Also create test executables
OPTION(BUILD_TESTS "Build tests" OFF)
OPTION(ENABLE_LIBPCI "Enable libpci" ON)
OPTION(ENABLE_VULKAN "Enable vulkan" ON)
@@ -19,7 +23,17 @@ OPTION(ENABLE_DCONF "Enable dconf" ON)
OPTION(ENABLE_DBUS "Enable dbus-1" ON)
OPTION(ENABLE_XFCONF "Enable libxfconf-0" ON)
OPTION(ENABLE_RPM "Enable rpm" ON)
OPTION(BUILD_TESTS "Build tests" ON)
# Track commits between version bumps for output in --version
if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git describe --tags
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE PROJECT_VERSION_TWEAK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
@@ -51,7 +65,7 @@ find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
# Init CMake targets.
# Init CMake targets
add_library(libfastfetch STATIC
src/util/FFstrbuf.c
@@ -263,7 +277,7 @@ target_link_libraries(flashfetch
PRIVATE libfastfetch
)
# Testing.
# Testing
if (BUILD_TESTS)
add_executable(fastfetch-test-performance
@@ -284,7 +298,9 @@ if (BUILD_TESTS)
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
endif()
# Installation.
# Installation
include(GNUInstallDirs)
install(
TARGETS fastfetch
@@ -306,3 +322,36 @@ install(
FILES ./LICENSE
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}
)
# Packaging
set(CPACK_GENERATOR "DEB;RPM;TGZ;ZIP")
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Neofetch clone written in C")
set(CPACK_PACKAGE_DESCRIPTION "
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
It is written in c to achieve much better performance.
")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/LinusDierheimer")
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "
libpci3
libvulkan1
libwayland-client0
libxcb-randr0
xcb
libxrandr2
libx11-6
libdconf1
libglib2.0-0
libdbus-1-3
libxfconf-0-3
")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
include(CPack)
+2 -2
View File
@@ -42,7 +42,7 @@ Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resoluti
##### Logos
```
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Linux, Manjaro, Mint, Pop!_OS, RebornOS, Ubuntu, Void, Zorin
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Linux, Manjaro, Mint, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, 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.
@@ -86,7 +86,7 @@ If pkg-config fails to find the headers for a library listed in [dependencies](#
* [AUR](https://aur.archlinux.org/packages/fastfetch-git/): Packaged by me. Will install the fastfetch binary, bash completion and the presets. Git version
* [Manjaro Repositories](https://gitlab.manjaro.org/packages/community/fastfetch): Packaged by a manjaro maintainer. Usually a bit outdated.
* [Gentoo (Guru)](https://github.com/gentoo/guru/tree/master/app-misc/fastfetch): Packed by some other guy. May be out of date some times.
* DEB: Run [`packaging/deb/create.sh`](packaging/deb/create.sh) from the root directory. You can give a custom build directory as an argument.
* DEB / RPM: Run `cmake -B build && cmake --build build --target package` to build the packages in build.
* Manually:
* Build: Follow the [build instructions](#building).
* Install: `sudo cmake --install build --prefix /usr/local`
Submodule packaging/aur deleted from 7ac9c5d132
-13
View File
@@ -1,13 +0,0 @@
Package: fastfetch
Version: <VERSION>
Section: utils
Priority: extra
Architecture: amd64
Maintainer: Linus@Dierheimer.de
Homepage: https://github.com/LinusDierheimer/fastfetch
Installed-Size: 410K
Description: A fast alternative to neofetch
fastfetch is a neofetch-like tool for fetching system information and
displaying them in a pretty way. It is written in c to achieve much better
performance, in return only Linux and Android are supported. It also uses
mechanisms like multithreading and caching to finish as fast as possible.
-28
View File
@@ -1,28 +0,0 @@
#!/bin/sh
# This script is intended to be run from the root of the repository.
# If you don't want to use build/ as build directoy, or already build the elsewere, you can give the build directoy as argument.
BUILD_DIR="${1:-build}"
ROOT_DIR="${2:-.}"
PACKAGE_DIR="${BUILD_DIR}/packaging/deb/fastfetch"
# Create missing files
mkdir -p "${BUILD_DIR}" || exit 1
if [ ! -f "${BUILD_DIR}/cmake_install.cmake" ]; then
cmake -S "${ROOT_DIR}" -B "${BUILD_DIR}" || exit 2
rm -f "${BUILD_DIR}/fastfetch" || exit 3 # Always rebuild the project if we reconfigured it
fi
if [ ! -f "${BUILD_DIR}/fastfetch" ]; then
cmake --build "${BUILD_DIR}" || exit 4
fi
# Populate the files
cmake --install "${BUILD_DIR}" --prefix "${PACKAGE_DIR}/usr" || exit 5
mkdir -p "${PACKAGE_DIR}/DEBIAN" || exit 6
sed "s/<VERSION>/$("${BUILD_DIR}/fastfetch" --version)/g" "${ROOT_DIR}/packaging/deb/control-template" > "${PACKAGE_DIR}/DEBIAN/control" || exit 7
# Create the package
dpkg-deb --build "${PACKAGE_DIR}" || exit 8
+4 -4
View File
@@ -246,9 +246,10 @@ void ffCacheValidate(FFinstance* instance)
ffStrbufInit(&content);
ffAppendFileContent(path.chars, &content);
if(ffStrbufCompS(&content, FASTFETCH_PROJECT_VERSION) == 0)
bool isSameVersion = ffStrbufCompS(&content, FASTFETCH_PROJECT_VERSION) == 0;
ffStrbufDestroy(&content);
if(isSameVersion)
{
ffStrbufDestroy(&content);
ffStrbufDestroy(&path);
return;
}
@@ -261,7 +262,6 @@ void ffCacheValidate(FFinstance* instance)
ffWriteFileContent(path.chars, &version);
ffStrbufDestroy(&version);
ffStrbufDestroy(&content);
ffStrbufDestroy(&path);
}
@@ -409,7 +409,7 @@ bool ffWriteFDContent(int fd, const FFstrbuf* content)
void ffWriteFileContent(const char* fileName, const FFstrbuf* content)
{
int fd = open(fileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
int fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if(fd == -1)
return;
+109
View File
@@ -775,6 +775,111 @@ static const FFlogo* getLogoMintOld()
FF_LOGO_RETURN
}
static const FFlogo* getLogoOpenSuse()
{
FF_LOGO_INIT
FF_LOGO_NAMES("suse", "opensuse", "open_suse", "open-suse", "suse-linux")
FF_LOGO_LINES(
"$2 .;ldkO0000Okdl;. \n"
"$2 .;d00xl:^''''''^:ok00d;. \n"
"$2 .d00l' 'o00d. \n"
"$2 .d0Kd'$1 Okxol:;,. $2:O0d \n"
"$2 .OK$1KKK0kOKKKKKKKKKKOxo:, $2lKO. \n"
"$2 ,0K$1KKKKKKKKKKKKKKK0P^$2,,,$1^dx:$2 ;00, \n"
"$2.OK$1KKKKKKKKKKKKKKKk'$2.oOPPb.$1'0k.$2 cKO.\n"
"$2:KK$1KKKKKKKKKKKKKKK: $2kKx..dd $1lKd$2 'OK:\n"
"$2dKK$1KKKKKKKKKOx0KKKd $2^0KKKO' $1kKKc$2 dKd\n"
"$2dKK$1KKKKKKKKKK;.;oOKx,..$2^$1..;kKKK0.$2 dKd\n"
"$2:KK$1KKKKKKKKKK0o;...^cdxxOK0O/^^' $2.0K:\n"
"$2 kKK$1KKKKKKKKKKKKK0x;,,......,;od $2lKk \n"
"$2 '0K$1KKKKKKKKKKKKKKKKKKKK00KKOo^ $2c00' \n"
"$2 'kK$1KKOxddxkOO00000Okxoc;'' $2.dKk' \n"
"$2 l0Ko. .c00l' \n"
"$2 'l0Kk:. .;xK0l' \n"
"$2 'lkK0xl:;,,,,;:ldO0kl' \n"
"$2 '^:ldxkkkkxdl:^' "
)
FF_LOGO_COLORS(
"32", //green
"37" //white
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoOpenSuseSmall()
{
FF_LOGO_INIT
FF_LOGO_NAMES("suse_small", "opensuse_small", "open_suse_small", "open-suse_small")
FF_LOGO_LINES(
"$1 _______ \n"
"$1__| __ \\ \n"
"$1 / .\\ \\\n"
"$1 \\__/ |\n"
"$1 _______|\n"
"$1 \\_______\n"
"$1__________/"
)
FF_LOGO_COLORS(
"32" //green
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoOpenSuseLeap()
{
FF_LOGO_INIT
FF_LOGO_NAMES("opensuse_leap", "open_suse_leap", "opensuse-leap", "open-suse-leap", "suse_leap", "suse-leap", "opensuseleap")
FF_LOGO_LINES(
"$2 .-++:. \n"
"$2 ./oooooo/- \n"
"$2 `:oooooooooooo:. \n"
"$2 -+oooooooooooooooo+-` \n"
"$2 ./oooooooooooooooooooooo/- \n"
"$2 :oooooooooooooooooooooooooo: \n"
"$2 ` `-+oooooooooooooooooooo/- ` \n"
"$2 `:oo/- .:ooooooooooooooo+:` `-+oo/. \n"
"$2`/oooooo:. -/oooooooooo/. ./oooooo/.\n"
"$2 `:+ooooo+-` `:+oooo+- `:oooooo+:` \n"
"$2 .:oooooo/. .::` -+oooooo/. \n"
"$2 -/oooooo:. ./oooooo+- \n"
"$2 `:+ooooo+-:+oooooo:` \n"
"$2 ./oooooooooo/. \n"
"$2 -/oooo+:` \n"
"$2 `:/. "
)
FF_LOGO_COLORS(
"32", //green
"37" //white
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoOpenSuseTumbleweed()
{
FF_LOGO_INIT
FF_LOGO_NAMES("opensuse_tumbleweed", "open_suse_tumbleweed", "opensuse-tumbleweed", "open-suse-tumbleweed", "suse_tumbleweed", "suse-tumbleweed", "opensusetumbleweed")
FF_LOGO_LINES(
"$2 ...... \n"
"$2 .,cdxxxoc,. .:kKMMMNWMMMNk:. \n"
"$2 cKMMN0OOOKWMMXo. ; ;0MWk:. .:OMMk. \n"
"$2 ;WMK;. .lKMMNM, :NMK, .OMW; \n"
"$2 cMW; 'WMMMN ,XMK, oMM'\n"
"$2.MMc ..;l. xMN: KM0\n"
"$2'MM. 'NMO oMM\n"
"$2.MM, .kMMl xMN\n"
"$2 KM0 .kMM0. .dl:,.. .WMd\n"
"$2 .XM0. ,OMMK, OMMMK. .XMK \n"
"$2 oWMO:. .;xNMMk, NNNMKl. .xWMx \n"
"$2 :ONMMNXMMMKx; . ,xNMWKkxllox0NMWk, \n"
"$2 ..... .:dOOXXKOxl, "
)
FF_LOGO_COLORS(
"32", //green
"37" //white
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoPop()
{
FF_LOGO_INIT
@@ -1048,6 +1153,10 @@ static GetLogoMethod* getLogoMethods()
getLogoMint,
getLogoMintSmall,
getLogoMintOld,
getLogoOpenSuse,
getLogoOpenSuseSmall,
getLogoOpenSuseLeap,
getLogoOpenSuseTumbleweed,
getLogoPop,
getLogoPopSmall,
getLogoReborn,
+110 -61
View File
@@ -53,20 +53,25 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
return true;
}
if(argType != DBUS_TYPE_ARRAY)
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
return false;
DBusMessageIter arrayIter;
data->ffdbus_message_iter_recurse(iter, &arrayIter);
DBusMessageIter subIter;
data->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
return getValue(&subIter, result, data);
//At this point we have an array
bool foundAValue = false;
while(true)
{
if((foundAValue = getValue(&arrayIter, result, data)))
if((foundAValue = getValue(&subIter, result, data)))
ffStrbufAppendS(result, ", ");
FF_DBUS_ITER_CONTINUE(arrayIter);
FF_DBUS_ITER_CONTINUE(subIter);
}
if(foundAValue)
@@ -75,51 +80,90 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
return foundAValue;
}
static bool detectSong(const char* player, FFMediaResult* result, DBusData* data)
static DBusMessage* getReply(DBusMessage* request, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call(player, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get");
DBusPendingCall* pendingCall = NULL;
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, DBUS_TIMEOUT_USE_DEFAULT);
data->ffdbus_message_unref(request);
if(!succesfull || pendingCall == NULL)
return NULL;
data->ffdbus_connection_flush(data->connection);
data->ffdbus_pending_call_block(pendingCall);
DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pendingCall);
data->ffdbus_pending_call_unref(pendingCall);
return reply;
}
static DBusMessage* getProperty(const char* busName, const char* objectPath, const char* interface, const char* property, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
if(message == NULL)
return false;
return NULL;
DBusMessageIter requestIterator;
data->ffdbus_message_iter_init_append(message, &requestIterator);
const char* arg1 = "org.mpris.MediaPlayer2.Player";
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &arg1))
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
data->ffdbus_message_unref(message);
return false;
return NULL;
}
const char* arg2 = "Metadata";
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &arg2))
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
data->ffdbus_message_unref(message);
return false;
return NULL;
}
DBusPendingCall* pending;
bool sendSuccessfull = data->ffdbus_connection_send_with_reply(data->connection, message, &pending, DBUS_TIMEOUT_USE_DEFAULT);
data->ffdbus_message_unref(message);
if(pending == NULL || !sendSuccessfull)
return false;
return getReply(message, data);
}
data->ffdbus_connection_flush(data->connection);
data->ffdbus_pending_call_block(pending);
static void getPropertyString(const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, objectPath, interface, property, data);
if(reply == NULL)
return;
DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pending);
data->ffdbus_pending_call_unref(pending);
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return;
}
getValue(&rootIterator, result, data);
data->ffdbus_message_unref(reply);
}
static bool getBusProperties(const char* busName, FFMediaResult* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata", data);
if(reply == NULL)
return false;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator) || data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return false;
}
if(data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
{
data->ffdbus_message_unref(reply);
return false;
}
DBusMessageIter variantIterator;
data->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
if(data->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
{
data->ffdbus_message_unref(reply);
return false;
}
DBusMessageIter arrayIterator;
data->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
@@ -143,18 +187,14 @@ static bool detectSong(const char* player, FFMediaResult* result, DBusData* data
data->ffdbus_message_iter_next(&dictIterator);
if(data->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_VARIANT)
FF_DBUS_ITER_CONTINUE(arrayIterator)
DBusMessageIter valueIter;
data->ffdbus_message_iter_recurse(&dictIterator, &valueIter);
if(strcmp(key, "xesam:title") == 0)
getValue(&valueIter, &result->song, data);
getValue(&dictIterator, &result->song, data);
else if(strcmp(key, "xesam:album") == 0)
getValue(&valueIter, &result->album, data);
getValue(&dictIterator, &result->album, data);
else if(strcmp(key, "xesam:artist") == 0)
getValue(&valueIter, &result->artist, data);
getValue(&dictIterator, &result->artist, data);
else if(strcmp(key, "xesam:url") == 0)
getValue(&dictIterator, &result->url, data);
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0)
break;
@@ -162,52 +202,52 @@ static bool detectSong(const char* player, FFMediaResult* result, DBusData* data
FF_DBUS_ITER_CONTINUE(arrayIterator)
}
data->ffdbus_message_unref(reply);
if(result->song.length == 0)
{
ffStrbufClear(&result->artist);
ffStrbufClear(&result->album);
ffStrbufClear(&result->url);
return false;
}
//We found a song, get the player name
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player, data);
if(result->player.length == 0)
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player, data);
return true;
}
static void getCustomPlayer(FFinstance* instance, FFMediaResult* result, DBusData* data)
static void getCustomBus(FFinstance* instance, FFMediaResult* result, DBusData* data)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
{
detectSong(instance->config.playerName.chars, result, data);
ffStrbufAppendS(&result->player, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result->busNameShort, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
getBusProperties(instance->config.playerName.chars, result, data);
return;
}
ffStrbufAppend(&result->busNameShort, &instance->config.playerName);
FFstrbuf busName;
ffStrbufInit(&busName);
ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX);
ffStrbufAppend(&busName, &instance->config.playerName);
detectSong(busName.chars, result, data);
getBusProperties(busName.chars, result, data);
ffStrbufDestroy(&busName);
ffStrbufAppend(&result->player, &instance->config.playerName);
}
static void getBestPlayer(FFMediaResult* result, DBusData* data)
static void getBestBus(FFMediaResult* result, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
if(message == NULL)
return;
DBusPendingCall* pending;
bool sendSuccessfull = data->ffdbus_connection_send_with_reply(data->connection, message, &pending, DBUS_TIMEOUT_USE_DEFAULT);
data->ffdbus_message_unref(message);
if(pending == NULL || !sendSuccessfull)
return;
data->ffdbus_connection_flush(data->connection);
data->ffdbus_pending_call_block(pending);
DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pending);
data->ffdbus_pending_call_unref(pending);
DBusMessage* reply = getReply(message, data);
if(reply == NULL)
return;
@@ -223,20 +263,22 @@ static void getBestPlayer(FFMediaResult* result, DBusData* data)
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(arrayIterator)
const char* name;
data->ffdbus_message_iter_get_basic(&arrayIterator, &name);
const char* busName;
data->ffdbus_message_iter_get_basic(&arrayIterator, &busName);
if(strncmp(name, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
if(strncmp(busName, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(detectSong(name, result, data))
if(getBusProperties(busName, result, data))
{
ffStrbufAppendS(&result->player, name + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result->busNameShort, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
break;
}
FF_DBUS_ITER_CONTINUE(arrayIterator)
}
data->ffdbus_message_unref(reply);
}
static void getMedia(FFinstance* instance, FFMediaResult* result)
@@ -269,9 +311,9 @@ static void getMedia(FFinstance* instance, FFMediaResult* result)
}
if(instance->config.playerName.length > 0)
getCustomPlayer(instance, result, &data);
getCustomBus(instance, result, &data);
else
getBestPlayer(result, &data);
getBestBus(result, &data);
dlclose(dbus);
}
@@ -292,23 +334,30 @@ const FFMediaResult* ffDetectMedia(FFinstance* instance)
}
init = true;
ffStrbufInit(&result.busNameShort);
ffStrbufInit(&result.player);
ffStrbufInit(&result.song);
ffStrbufInit(&result.artist);
ffStrbufInit(&result.album);
ffStrbufInit(&result.url);
#ifdef FF_HAVE_DBUS
getMedia(instance, &result);
#endif
if(instance->config.playerName.length > 0 && result.player.length == 0)
//Set busNameShort if a custom player was given, but loading dbus failed
if(instance->config.playerName.length > 0 && result.busNameShort.length == 0)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
ffStrbufAppendS(&result.player, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
ffStrbufAppendS(&result.busNameShort, instance->config.playerName.chars + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
else
ffStrbufAppend(&result.player, &instance->config.playerName);
ffStrbufAppend(&result.busNameShort, &instance->config.playerName);
}
//Set player to busNameShort, if detection failed
if(result.player.length == 0)
ffStrbufAppend(&result.player, &result.busNameShort);
pthread_mutex_unlock(&mutex);
return &result;
}
+13 -4
View File
@@ -304,16 +304,20 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "player-format") == 0)
{
constructAndPrintCommandHelpFormat("player", "{}", 1,
"Player name"
constructAndPrintCommandHelpFormat("player", "{}", 3,
"Pretty player name",
"Player name",
"DBus bus name"
);
}
else if(strcasecmp(command, "song-format") == 0)
{
constructAndPrintCommandHelpFormat("song", "{2} - {3} - {1}", 3,
constructAndPrintCommandHelpFormat("song", "{3} - {4} - {1}", 5,
"Song name pretty",
"Song name",
"Artist name",
"Album name"
"Album name",
"Song url"
);
}
else if(strcasecmp(command, "datetime-format") == 0 || strcasecmp(command, "date-format") == 0 || strcasecmp(command, "time-format") == 0)
@@ -612,6 +616,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
exit(0);
}
else if(strcasecmp(key, "-v") == 0 || strcasecmp(key, "--version") == 0)
{
puts("fastfetch "FASTFETCH_PROJECT_VERSION""FASTFETCH_PROJECT_VERSION_TWEAK);
exit(0);
}
else if(strcasecmp(key, "--version-raw") == 0)
{
puts(FASTFETCH_PROJECT_VERSION);
exit(0);
+3 -1
View File
@@ -257,10 +257,12 @@ typedef struct FFTempsResult
typedef struct FFMediaResult
{
FFstrbuf player;
FFstrbuf busNameShort; //e.g. plasma-browser-integration
FFstrbuf player; // e.g. Google Chrome
FFstrbuf song;
FFstrbuf artist;
FFstrbuf album;
FFstrbuf url;
} FFMediaResult;
typedef struct FFDateTimeResult
+1
View File
@@ -4,6 +4,7 @@
#define FASTFETCH_PROJECT_NAME "@PROJECT_NAME@"
#define FASTFETCH_PROJECT_VERSION "@PROJECT_VERSION@"
#define FASTFETCH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define FASTFETCH_PROJECT_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@"
#define FASTFETCH_DATATEXT_STRUCTURE "@DATATEXT_STRUCTURE@"
#define FASTFETCH_DATATEXT_CONFIG "@DATATEXT_CONFIG@" //Requires FASTFETCH_PROJECT_VERSION and FASTFETCH_DATATEXT_STRUCTURE to be set
+42 -3
View File
@@ -1,7 +1,9 @@
#include "fastfetch.h"
#include <ctype.h>
#define FF_PLAYER_MODULE_NAME "Media Player"
#define FF_PLAYER_NUM_FORMAT_ARGS 1
#define FF_PLAYER_NUM_FORMAT_ARGS 3
void ffPrintPlayer(FFinstance* instance)
{
@@ -13,15 +15,52 @@ void ffPrintPlayer(FFinstance* instance)
return;
}
FFstrbuf playerPretty;
ffStrbufInit(&playerPretty);
//If we are on a website, prepend the website name
if(ffStrbufStartsWithS(&media->url, "https://www."))
ffStrbufAppendS(&playerPretty, media->url.chars + 12);
else if(ffStrbufStartsWithS(&media->url, "http://www."))
ffStrbufAppendS(&playerPretty, media->url.chars + 11);
else if(ffStrbufStartsWithS(&media->url, "https://"))
ffStrbufAppendS(&playerPretty, media->url.chars + 8);
else if(ffStrbufStartsWithS(&media->url, "http://"))
ffStrbufAppendS(&playerPretty, media->url.chars + 7);
//If we found a website name, make it more pretty
if(playerPretty.length > 0)
{
ffStrbufSubstrBeforeFirstC(&playerPretty, '/'); //Remove the path
ffStrbufSubstrBeforeLastC(&playerPretty, '.'); //Remove the TLD
}
//Check again for length, as we may have removed everything.
bool playerPrettyIsCustom = playerPretty.length > 0;
//If we don't have subdomains, it is usually more pretty to capitalize the first letter.
if(playerPrettyIsCustom && ffStrbufFirstIndexC(&playerPretty, '.') == playerPretty.length)
playerPretty.chars[0] = (char) toupper(playerPretty.chars[0]);
if(playerPrettyIsCustom)
ffStrbufAppendS(&playerPretty, " (");
ffStrbufAppend(&playerPretty, &media->player);
if(playerPrettyIsCustom)
ffStrbufAppendC(&playerPretty, ')');
if(instance->config.playerFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey);
ffStrbufPutTo(&media->player, stdout);
ffStrbufPutTo(&playerPretty, stdout);
}
else
{
ffPrintFormatString(instance, FF_PLAYER_MODULE_NAME, 0, &instance->config.playerKey, &instance->config.playerFormat, NULL, FF_PLAYER_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &media->player}
{FF_FORMAT_ARG_TYPE_STRBUF, &playerPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->player},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->busNameShort}
});
}
}
+73 -6
View File
@@ -1,7 +1,44 @@
#include "fastfetch.h"
#include <ctype.h>
#define FF_SONG_MODULE_NAME "Song"
#define FF_SONG_NUM_FORMAT_ARGS 3
#define FF_SONG_NUM_FORMAT_ARGS 5
static bool shouldIgoreChar(char c)
{
return isblank(c) || c == '-' || c == '.';
}
static bool artistInSongTitle(const FFstrbuf* song, const FFstrbuf* artist)
{
uint32_t artistIndex = 0;
uint32_t songIndex = 0;
while(true)
{
while(shouldIgoreChar(song->chars[songIndex]))
++songIndex;
while(shouldIgoreChar(artist->chars[artistIndex]))
++artistIndex;
if(artist->chars[artistIndex] == '\0')
return true;
if(song->chars[songIndex] == '\0')
return false;
if(tolower(song->chars[songIndex]) != tolower(artist->chars[artistIndex]))
return false;
++artistIndex;
++songIndex;
}
//Unreachable
return false;
}
void ffPrintSong(FFinstance* instance)
{
@@ -13,30 +50,60 @@ void ffPrintSong(FFinstance* instance)
return;
}
FFstrbuf songPretty;
ffStrbufInitCopy(&songPretty, &media->song);
const char* removeStrings[] = {
"(Official Music Video)", "(Official Video)", "(Music Video)",
"[Official Music Video]", "[Official Video]", "[Music Video]",
"| Official Music Video", "| Official Video", "| Music Video",
"[Official Audio]", "[Audio]", "(Audio)", "| Official Audio", "| Audio", "| OFFICIAL AUDIO",
"(Lyric Video)", "(Official Lyric Video)", "(Lyrics)",
"[Lyric Video]", "[Official Lyric Video]", "[Lyrics]",
"| Lyric Video", "| Official Lyric Video", "| Lyrics",
};
ffStrbufRemoveStringsA(&songPretty, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
ffStrbufTrimRight(&songPretty, ' ');
if(songPretty.length == 0)
ffStrbufAppend(&songPretty, &media->song);
if(instance->config.songFormat.length == 0)
{
//We don't expose artistPretty to the format, as it might be empty (when the think that the artist is already in the song title)
FFstrbuf artistPretty;
ffStrbufInitCopy(&artistPretty, &media->artist);
ffStrbufRemoveIgnCaseEndS(&artistPretty, " - Topic");
ffStrbufRemoveIgnCaseEndS(&artistPretty, "VEVO");
ffStrbufTrimRight(&artistPretty, ' ');
if(artistInSongTitle(&songPretty, &artistPretty))
ffStrbufClear(&artistPretty);
ffPrintLogoAndKey(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey);
if(media->artist.length > 0)
if(artistPretty.length > 0)
{
ffStrbufWriteTo(&media->artist, stdout);
ffStrbufWriteTo(&artistPretty, stdout);
fputs(" - ", stdout);
}
if(media->album.length > 0)
//Some sites (e.g. reddit) expose their url as album. We don't want to show that
if(media->album.length > 0 && !ffStrbufStartsWithIgnCaseS(&media->album, "http"))
{
ffStrbufWriteTo(&media->album, stdout);
fputs(" - ", stdout);
}
ffStrbufPutTo(&media->song, stdout);
ffStrbufPutTo(&songPretty, stdout);
}
else
{
ffPrintFormatString(instance, FF_SONG_MODULE_NAME, 0, &instance->config.songKey, &instance->config.songFormat, NULL, FF_SONG_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &songPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->song},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->artist},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->album}
{FF_FORMAT_ARG_TYPE_STRBUF, &media->album},
{FF_FORMAT_ARG_TYPE_STRBUF, &media->url}
});
}
}