diff --git a/CMakeLists.txt b/CMakeLists.txt index cb7ed9dc0..488ec3f18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,7 +298,7 @@ set(LIBFASTFETCH_SRC src/modules/display/display.c src/modules/separator/separator.c src/modules/shell.c - src/modules/sound.c + src/modules/sound/sound.c src/modules/swap.c src/modules/media.c src/modules/terminal.c diff --git a/src/common/init.c b/src/common/init.c index fb2ce3889..d805d0724 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -103,7 +103,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.openCL); initModuleArg(&instance->config.users); ffInitBluetoothOptions(&instance->config.bluetooth); - initModuleArg(&instance->config.sound); + ffInitSoundOptions(&instance->config.sound); ffInitSeparatorOptions(&instance->config.separator); ffInitGamepadOptions(&instance->config.gamepad); @@ -136,8 +136,6 @@ static void defaultConfig(FFinstance* instance) instance->config.shellVersion = true; instance->config.terminalVersion = true; - instance->config.soundType = FF_SOUND_TYPE_MAIN; - instance->config.publicIpTimeout = 0; ffStrbufInit(&instance->config.publicIpUrl); @@ -328,7 +326,7 @@ static void destroyConfig(FFinstance* instance) destroyModuleArg(&instance->config.users); ffDestroyBluetoothOptions(&instance->config.bluetooth); ffDestroySeparatorOptions(&instance->config.separator); - destroyModuleArg(&instance->config.sound); + ffDestroySoundOptions(&instance->config.sound); ffDestroyGamepadOptions(&instance->config.gamepad); ffStrbufDestroy(&instance->config.libPCI); diff --git a/src/fastfetch.c b/src/fastfetch.c index e1884e5f6..50546fea8 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1023,7 +1023,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "users", &instance->config.users)) {} else if(ffParseBluetoothCommandOptions(&instance->config.bluetooth, key, value)) {} else if(ffParseSeparatorCommandOptions(&instance->config.separator, key, value)) {} - else if(optionParseModuleArgs(key, value, "sound", &instance->config.sound)) {} + else if(ffParseSoundCommandOptions(&instance->config.sound, key, value)) {} else if(ffParseGamepadCommandOptions(&instance->config.gamepad, key, value)) {} /////////////////// @@ -1095,15 +1095,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.shellVersion = optionParseBoolean(value); else if(strcasecmp(key, "--terminal-version") == 0) instance->config.terminalVersion = optionParseBoolean(value); - else if(strcasecmp(key, "--sound-type") == 0) - { - optionParseEnum(key, value, &instance->config.soundType, - "main", FF_SOUND_TYPE_MAIN, - "active", FF_SOUND_TYPE_ACTIVE, - "all", FF_SOUND_TYPE_ALL, - NULL - ); - } else if(strcasecmp(key, "--player-name") == 0) optionParseString(key, value, &instance->config.playerName); else if(strcasecmp(key, "--publicip-url") == 0) @@ -1274,10 +1265,10 @@ static void parseStructureCommand(FFinstance* instance, const char* line) ffPrintUsers(instance); else if(strcasecmp(line, FF_COMMAND_MODULE_NAME) == 0) ffPrintCommand(instance, &instance->config.command); - else if(strcasecmp(line, "bluetooth") == 0) + else if(strcasecmp(line, FF_BLUETOOTH_MODULE_NAME) == 0) ffPrintBluetooth(instance, &instance->config.bluetooth); - else if(strcasecmp(line, "sound") == 0) - ffPrintSound(instance); + else if(strcasecmp(line, FF_SOUND_MODULE_NAME) == 0) + ffPrintSound(instance, &instance->config.sound); else if(strcasecmp(line, FF_GAMEPAD_MODULE_NAME) == 0) ffPrintGamepad(instance, &instance->config.gamepad); else if(strcasecmp(line, FF_JSONCONFIG_MODULE_NAME) == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index 2068ab03b..1e6b9ee1e 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -19,13 +19,6 @@ static inline void ffUnused(int dummy, ...) { (void) dummy; } #include "modules/options.h" #include "logo/option.h" -typedef enum FFSoundType -{ - FF_SOUND_TYPE_MAIN, - FF_SOUND_TYPE_ACTIVE, - FF_SOUND_TYPE_ALL, -} FFSoundType; - typedef enum FFBinaryPrefixType { FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) @@ -110,7 +103,7 @@ typedef struct FFconfig FFModuleArgs users; FFBluetoothOptions bluetooth; FFSeparatorOptions separator; - FFModuleArgs sound; + FFSoundOptions sound; FFGamepadOptions gamepad; FFstrbuf libPCI; @@ -148,8 +141,6 @@ typedef struct FFconfig FFstrbuf weatherOutputFormat; uint32_t weatherTimeout; - FFSoundType soundType; - FFstrbuf playerName; uint32_t percentType; @@ -237,6 +228,5 @@ void ffPrintVulkan(FFinstance* instance); void ffPrintOpenGL(FFinstance* instance); void ffPrintOpenCL(FFinstance* instance); void ffPrintUsers(FFinstance* instance); -void ffPrintSound(FFinstance* instance); #endif diff --git a/src/flashfetch.c b/src/flashfetch.c index 4c0db155e..451d72ace 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -66,7 +66,7 @@ int main(int argc, char** argv) //ffPrintUsers(&instance); //ffPrintWeather(&instance); //ffPrintBluetooth(&instance); - //ffPrintSound(&instance); + //ffPrintSound(&instance, &instance.config.sound); //ffPrintGamepad(&instance); ffPrintBreak(&instance); ffPrintColors(&instance); diff --git a/src/modules/jsonconfig/jsonconfig.c b/src/modules/jsonconfig/jsonconfig.c index f1f12cd93..0311a4711 100644 --- a/src/modules/jsonconfig/jsonconfig.c +++ b/src/modules/jsonconfig/jsonconfig.c @@ -97,6 +97,7 @@ static bool parseModuleJsonObject(FFinstance* instance, const char* type, json_o case 'S': { return tryModule(instance, type, module, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorJsonObject) || + tryModule(instance, type, module, FF_SOUND_MODULE_NAME, ffParseSoundJsonObject) || false; } diff --git a/src/modules/modules.h b/src/modules/modules.h index 49c3fa56b..e2fff95f3 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -26,5 +26,6 @@ #include "modules/locale/locale.h" #include "modules/localip/localip.h" #include "modules/separator/separator.h" +#include "modules/sound/sound.h" #include "modules/title/title.h" #include "modules/jsonconfig/jsonconfig.h" diff --git a/src/modules/options.h b/src/modules/options.h index f8045ac9b..fc2b460a5 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -24,4 +24,5 @@ #include "modules/localip/option.h" #include "modules/os/option.h" #include "modules/separator/option.h" +#include "modules/sound/option.h" #include "modules/title/option.h" diff --git a/src/modules/sound.c b/src/modules/sound.c deleted file mode 100644 index ffc4aee76..000000000 --- a/src/modules/sound.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "common/printing.h" -#include "detection/sound/sound.h" - -#define FF_SOUND_MODULE_NAME "Sound" -#define FF_SOUND_NUM_FORMAT_ARGS 4 - -static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8_t index) -{ - if(instance->config.sound.outputFormat.length == 0) - { - ffPrintLogoAndKey(instance, FF_SOUND_MODULE_NAME, index, &instance->config.sound.key); - ffStrbufWriteTo(&device->name, stdout); - - if(device->volume != FF_SOUND_VOLUME_UNKNOWN) - { - if(device->volume > 0) - printf(" (%d%%)", device->volume); - else - fputs(" (muted)", stdout); - } - - if(device->main && index > 0) - fputs(" (*)", stdout); - - putchar('\n'); - } - else - { - ffPrintFormat(instance, FF_SOUND_MODULE_NAME, index, &instance->config.sound, FF_SOUND_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_BOOL, &device->main}, - {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, - {FF_FORMAT_ARG_TYPE_UINT8, &device->volume}, - {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier} - }); - } -} - -static void printSound(FFinstance* instance, FFlist* devices) -{ - FF_LIST_AUTO_DESTROY filtered; - ffListInit(&filtered, sizeof(FFSoundDevice*)); - - FF_LIST_FOR_EACH(FFSoundDevice, device, *devices) - { - switch (instance->config.soundType) - { - case FF_SOUND_TYPE_MAIN: if (!device->main) continue; break; - case FF_SOUND_TYPE_ACTIVE: if (!device->active) continue; break; - case FF_SOUND_TYPE_ALL: break; - } - - *(FFSoundDevice**)ffListAdd(&filtered) = device; - } - - if(filtered.length == 0) - { - ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &instance->config.sound, "No active sound devices found"); - return; - } - - uint8_t index = 1; - FF_LIST_FOR_EACH(FFSoundDevice*, device, filtered) - printDevice(instance, *device, filtered.length == 1 ? 0 : index++); -} - -void ffPrintSound(FFinstance* instance) -{ - FF_LIST_AUTO_DESTROY result; - ffListInit(&result, sizeof(FFSoundDevice)); - const char* error = ffDetectSound(instance, &result); - - if(error) - { - ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &instance->config.sound, "%s", error); - return; - } - - printSound(instance, &result); - - FF_LIST_FOR_EACH(FFSoundDevice, device, result) - { - ffStrbufDestroy(&device->identifier); - ffStrbufDestroy(&device->name); - } -} diff --git a/src/modules/sound/option.h b/src/modules/sound/option.h new file mode 100644 index 000000000..b0586036b --- /dev/null +++ b/src/modules/sound/option.h @@ -0,0 +1,20 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef enum FFSoundType +{ + FF_SOUND_TYPE_MAIN, + FF_SOUND_TYPE_ACTIVE, + FF_SOUND_TYPE_ALL, +} FFSoundType; + +typedef struct FFSoundOptions +{ + const char* moduleName; + FFModuleArgs moduleArgs; + + FFSoundType soundType; +} FFSoundOptions; diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c new file mode 100644 index 000000000..678c47b5d --- /dev/null +++ b/src/modules/sound/sound.c @@ -0,0 +1,154 @@ +#include "common/printing.h" +#include "detection/sound/sound.h" +#include "modules/sound/sound.h" + +#define FF_SOUND_NUM_FORMAT_ARGS 4 + +static void printDevice(FFinstance* instance, FFSoundOptions* options, const FFSoundDevice* device, uint8_t index) +{ + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_SOUND_MODULE_NAME, index, &options->moduleArgs.key); + ffStrbufWriteTo(&device->name, stdout); + + if(device->volume != FF_SOUND_VOLUME_UNKNOWN) + { + if(device->volume > 0) + printf(" (%d%%)", device->volume); + else + fputs(" (muted)", stdout); + } + + if(device->main && index > 0) + fputs(" (*)", stdout); + + putchar('\n'); + } + else + { + ffPrintFormat(instance, FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_SOUND_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_BOOL, &device->main}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, + {FF_FORMAT_ARG_TYPE_UINT8, &device->volume}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier} + }); + } +} + +void ffPrintSound(FFinstance* instance, FFSoundOptions* options) +{ + FF_LIST_AUTO_DESTROY result; + ffListInit(&result, sizeof(FFSoundDevice)); + const char* error = ffDetectSound(instance, &result); + + if(error) + { + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, "%s", error); + return; + } + + FF_LIST_AUTO_DESTROY filtered; + ffListInit(&filtered, sizeof(FFSoundDevice*)); + + FF_LIST_FOR_EACH(FFSoundDevice, device, result) + { + switch (options->soundType) + { + case FF_SOUND_TYPE_MAIN: if (!device->main) continue; break; + case FF_SOUND_TYPE_ACTIVE: if (!device->active) continue; break; + case FF_SOUND_TYPE_ALL: break; + } + + *(FFSoundDevice**)ffListAdd(&filtered) = device; + } + + if(filtered.length == 0) + { + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, "No active sound devices found"); + return; + } + + uint8_t index = 1; + FF_LIST_FOR_EACH(FFSoundDevice*, device, filtered) + { + printDevice(instance, options, *device, filtered.length == 1 ? 0 : index++); + } + + FF_LIST_FOR_EACH(FFSoundDevice, device, result) + { + ffStrbufDestroy(&device->identifier); + ffStrbufDestroy(&device->name); + } +} + + +void ffInitSoundOptions(FFSoundOptions* options) +{ + options->moduleName = FF_SOUND_MODULE_NAME; + ffOptionInitModuleArg(&options->moduleArgs); + + options->soundType = FF_SOUND_TYPE_MAIN; +} + +bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_SOUND_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + if (strcasecmp(subKey, "sound-type") == 0) + { + options->soundType = (FFSoundType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "main", FF_SOUND_TYPE_MAIN }, + { "active", FF_SOUND_TYPE_ACTIVE }, + { "all", FF_SOUND_TYPE_ALL }, + {}, + }); + return true; + } + + return false; +} + +void ffDestroySoundOptions(FFSoundOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +#ifdef FF_HAVE_JSONC +void ffParseSoundJsonObject(FFinstance* instance, json_object* module) +{ + FFSoundOptions __attribute__((__cleanup__(ffDestroySoundOptions))) options; + ffInitSoundOptions(&options); + + if (module) + { + json_object_object_foreach(module, key, val) + { + if (ffJsonConfigParseModuleArgs(key, val, &options.moduleArgs)) + continue; + + if (strcasecmp(key, "soundType") == 0) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "main", FF_SOUND_TYPE_MAIN }, + { "active", FF_SOUND_TYPE_ACTIVE }, + { "all", FF_SOUND_TYPE_ALL }, + {}, + }); + if (error) + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &options.moduleArgs, "Invalid %s value: %s", key, error); + else + options.soundType = (FFSoundType) value; + continue; + } + + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &options.moduleArgs, "Unknown JSON key %s", key); + } + } + + ffPrintSound(instance, &options); +} +#endif diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h new file mode 100644 index 000000000..fa9d8dc87 --- /dev/null +++ b/src/modules/sound/sound.h @@ -0,0 +1,16 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/title/option.h" + +#define FF_SOUND_MODULE_NAME "Sound" + +void ffPrintSound(FFinstance* instance, FFSoundOptions* options); +void ffInitSoundOptions(FFSoundOptions* options); +bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const char* value); +void ffDestroySoundOptions(FFSoundOptions* options); + +#ifdef FF_HAVE_JSONC +#include "common/jsonconfig.h" +void ffParseSoundJsonObject(FFinstance* instance, json_object* module); +#endif