diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c0370619..361f82016 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,7 @@ if(LINUX OR ANDROID OR BSD) list(APPEND LIBFASTFETCH_SRC src/detection/cpuUsage/cpuUsage_linux.c src/detection/battery/battery_linux.c + src/detection/disk/disk_linux.c ) endif() @@ -296,6 +297,7 @@ if(APPLE) src/detection/displayserver/displayserver_apple.c src/detection/terminalfont/terminalfont_apple.c src/detection/media/media_apple.m + src/detection/disk/disk_apple.m ) endif() diff --git a/src/common/init.c b/src/common/init.c index 10b07edc6..1037eb363 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -222,6 +222,7 @@ static void defaultConfig(FFinstance* instance) instance->config.titleFQDN = false; ffStrbufInitA(&instance->config.diskFolders, 0); + instance->config.diskRemovable = false; ffStrbufInitA(&instance->config.batteryDir, 0); diff --git a/src/data/help.txt b/src/data/help.txt index 283ca01a0..75f4fde5e 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -87,10 +87,11 @@ Library options: Set the path of a library to load --lib-plist Module specific options: - --title-fqdn : sets if the title should use fully qualified domain name. Default is false. + --title-fqdn : Sets if the title should use fully qualified domain name. Default is false. --separator-string : Set the string printed by the separator module --os-file : Set the path to the file containing OS informations --disk-folders : A colon separated list of folder paths for the disk output. Default is "/:/home" + --disk-removable : Sets if removable volume should be printed. Default is false --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ --localip-show-ipv4 : Show ipv4 addresses in local ip module. Default is true --localip-show-ipv6 : Show ipv6 addresses in local ip module. Default is false diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h new file mode 100644 index 000000000..aaf34a608 --- /dev/null +++ b/src/detection/disk/disk.h @@ -0,0 +1,10 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_disk_disk +#define FF_INCLUDED_detection_disk_disk + +#include "fastfetch.h" + +const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders); + +#endif diff --git a/src/detection/disk/disk_apple.m b/src/detection/disk/disk_apple.m new file mode 100644 index 000000000..95d5fd8ec --- /dev/null +++ b/src/detection/disk/disk_apple.m @@ -0,0 +1,25 @@ +#include "disk.h" + +#import + +const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders) +{ + NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, nil]; + NSArray *urls = [NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys:keys + options:NSVolumeEnumerationSkipHiddenVolumes]; + if(urls == nil) + return "[NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys] failed"; + + for (NSURL *url in urls) { + NSError *error; + NSNumber* removable; + if([url getResourceValue:&removable forKey:NSURLVolumeIsRemovableKey error:&error] == NO) + continue; + if(removable.boolValue && !instance->config.diskRemovable) + continue; + + ffStrbufInitS((FFstrbuf *)ffListAdd(folders), [url.relativePath cStringUsingEncoding:NSUTF8StringEncoding]); + } + + return NULL; +} diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c new file mode 100644 index 000000000..80d5808c4 --- /dev/null +++ b/src/detection/disk/disk_linux.c @@ -0,0 +1,22 @@ +#include "disk.h" + +#include + +const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders) +{ + FF_UNUSED(instance); + + struct statvfs fsRoot; + int rootRet = statvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot); + if(rootRet != 0) + return "statvfs(\"/\") failed"; + + ffStrbufInitS((FFstrbuf *)ffListAdd(folders), FASTFETCH_TARGET_DIR_ROOT"/"); + + struct statvfs fsHome; + int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome); + if(homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid)) + ffStrbufInitS((FFstrbuf *)ffListAdd(folders), FASTFETCH_TARGET_DIR_HOME); + + return NULL; +} diff --git a/src/detection/media/media_apple.m b/src/detection/media/media_apple.m index 6db70d048..39b0c932a 100644 --- a/src/detection/media/media_apple.m +++ b/src/detection/media/media_apple.m @@ -32,18 +32,27 @@ static const char* getMedia(FFMediaResult* result) }); dispatch_group_enter(group); + __block const char* error = NULL; MRMediaRemoteGetNowPlayingInfo(queue, ^(_Nullable CFDictionaryRef info) { - if(info != nil) { - ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song); - ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist); - ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album); + if(info != nil) + { + error = ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song); + if(!error) + { + ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist); + ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album); + } } + else + error = "MRMediaRemoteGetNowPlayingInfo() failed"; + dispatch_group_leave(group); }); dispatch_group_enter(group); MRMediaRemoteGetNowPlayingClient(queue, ^(_Nullable id clientObj) { - if (clientObj != nil) { + if (clientObj != nil) + { CFStringRef identifier = MRNowPlayingClientGetBundleIdentifier(clientObj); if (identifier == nil) identifier = MRNowPlayingClientGetParentAppBundleIdentifier(clientObj); @@ -65,7 +74,7 @@ static const char* getMedia(FFMediaResult* result) if(result->song.length > 0) return NULL; - return "MediaRemote failed"; + return error; } void ffDetectMediaImpl(const FFinstance* instance, FFMediaResult* media) diff --git a/src/fastfetch.c b/src/fastfetch.c index 6c43171be..359b0449e 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1255,6 +1255,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.titleFQDN = optionParseBoolean(value); else if(strcasecmp(key, "--disk-folders") == 0) optionParseString(key, value, &instance->config.diskFolders); + else if(strcasecmp(key, "--disk-removable") == 0) + instance->config.diskRemovable = optionParseBoolean(value); else if(strcasecmp(key, "--battery-dir") == 0) optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index 21f2920e7..8d4447bf9 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -154,6 +154,7 @@ typedef struct FFconfig bool titleFQDN; FFstrbuf diskFolders; + bool diskRemovable; FFstrbuf batteryDir; diff --git a/src/modules/disk.c b/src/modules/disk.c index 86049705d..ea92f7e89 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -1,6 +1,7 @@ #include "fastfetch.h" #include "common/printing.h" #include "common/parsing.h" +#include "detection/disk/disk.h" #include @@ -64,49 +65,7 @@ static void printStatvfs(FFinstance* instance, const FFstrbuf* key, const char* ffStrbufDestroy(&usedPretty); } -static void printFolderAutodetection(FFinstance* instance, const char* folderPath, struct statvfs* fs) -{ - FFstrbuf key; - ffStrbufInit(&key); - createKey(instance, folderPath, &key); - printStatvfs(instance, &key, folderPath, fs); - ffStrbufDestroy(&key); -} - -static void printFoldersAutodetection(FFinstance* instance) -{ - struct statvfs fsRoot; - int rootRet = statvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot); - - if(rootRet != 0) - { - FFstrbuf key; - ffStrbufInit(&key); - createKey(instance, NULL, &key); - ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs for / returned not zero: %i", rootRet); - ffStrbufDestroy(&key); - return; - } - - //On MacOS statvfs seems to return different f_fsid for the same filesystem. - //Since it isn't really possible to install /Users on a separate disk anyway, just never print it by default. - #ifndef __APPLE__ - struct statvfs fsHome; - int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome); - bool printHome = homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid); - #else - bool printHome = false; - #endif // !__APPLE__ - - printFolderAutodetection(instance, printHome ? FASTFETCH_TARGET_DIR_ROOT"/" : NULL, &fsRoot); - - #ifndef __APPLE__ - if(printHome) - printFolderAutodetection(instance, FASTFETCH_TARGET_DIR_HOME, &fsHome); - #endif // !__APPLE__ -} - -static void printFolderCustom(FFinstance* instance, const char* folderPath) +static void printFolder(FFinstance* instance, const char* folderPath) { FFstrbuf key; ffStrbufInit(&key); @@ -131,17 +90,28 @@ void ffPrintDisk(FFinstance* instance) if(instance->config.diskFolders.length == 0) { - printFoldersAutodetection(instance); + FFlist folders; + ffListInit(&folders, sizeof(FFstrbuf)); + const char* error = ffDiskAutodetectFolders(instance, &folders); + if(error) + ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", error); + for(uint32_t i = 0; i < folders.length; ++i) + { + FFstrbuf* folder = (FFstrbuf*)ffListGet(&folders, i); + printFolder(instance, folder->chars); + ffStrbufDestroy(folder); + } + ffListDestroy(&folders); return; } uint32_t startIndex = 0; - while (startIndex < instance->config.diskFolders.length) + while(startIndex < instance->config.diskFolders.length) { uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':'); instance->config.diskFolders.chars[colonIndex] = '\0'; - printFolderCustom(instance, instance->config.diskFolders.chars + startIndex); + printFolder(instance, instance->config.diskFolders.chars + startIndex); startIndex = colonIndex + 1; } diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 32acc486c..65dcd7248 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -6,7 +6,11 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result) //CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string ffStrbufEnsureFree(result, length * 2); if(!CFStringGetCString(str, result->chars, result->allocated, kCFStringEncodingUTF8)) - return "CFStringGetCString() failed"; + { + ffStrbufEnsureFree(result, length * 4); + if(!CFStringGetCString(str, result->chars, result->allocated, kCFStringEncodingUTF8)) + return "CFStringGetCString() failed"; + } // CFStringGetCString ensures the buffer is NUL terminated // https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring result->length = (uint32_t) strnlen(result->chars, (uint32_t)result->allocated);