ok well it . compiles and runs so

This commit is contained in:
Mars 2025-04-27 14:03:10 -04:00
parent 350e3a13db
commit b534cbddb0
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
4 changed files with 91 additions and 51 deletions

View file

@ -9,37 +9,40 @@
#include "os.h" #include "os.h"
#include "src/util/types.h" #include "src/util/types.h"
fn os::GetMemInfo() -> Result<u64, String> { fn os::GetMemInfo() -> Result<u64, OsError> {
u64 mem = 0; u64 mem = 0;
usize size = sizeof(mem); usize size = sizeof(mem);
if (sysctlbyname("hw.memsize", &mem, &size, nullptr, 0) == -1) if (sysctlbyname("hw.memsize", &mem, &size, nullptr, 0) == -1)
return Err(std::format("sysctlbyname failed: {}", strerror(errno))); return Err(OsError::withErrno("Failed to get memory info"));
return mem; return mem;
} }
fn os::GetNowPlaying() -> Result<String, NowPlayingError> { return GetCurrentPlayingInfo(); } fn os::GetNowPlaying() -> Result<MediaInfo, NowPlayingError> { return GetCurrentPlayingInfo(); }
fn os::GetOSVersion() -> Result<String, String> { return GetMacOSVersion(); } fn os::GetOSVersion() -> Result<String, OsError> { return GetMacOSVersion(); }
fn os::GetDesktopEnvironment() -> Option<String> { return None; } fn os::GetDesktopEnvironment() -> Option<String> { return None; }
fn os::GetWindowManager() -> String { return "Yabai"; } fn os::GetWindowManager() -> Option<String> { return None; }
fn os::GetKernelVersion() -> String { fn os::GetKernelVersion() -> Result<String, OsError> {
std::array<char, 256> kernelVersion {}; std::array<char, 256> kernelVersion {};
usize kernelVersionLen = sizeof(kernelVersion); usize kernelVersionLen = sizeof(kernelVersion);
sysctlbyname("kern.osrelease", std::span(kernelVersion).data(), &kernelVersionLen, nullptr, 0); if (sysctlbyname("kern.osrelease", kernelVersion.data(), &kernelVersionLen, nullptr, 0) == -1)
return Err(OsError::withErrno("Failed to get kernel version"));
return kernelVersion.data(); return kernelVersion.data();
} }
fn os::GetHost() -> String { fn os::GetHost() -> Result<String, OsError> {
std::array<char, 256> hwModel {}; std::array<char, 256> hwModel {};
size_t hwModelLen = sizeof(hwModel); size_t hwModelLen = sizeof(hwModel);
sysctlbyname("hw.model", hwModel.data(), &hwModelLen, nullptr, 0); if (sysctlbyname("hw.model", hwModel.data(), &hwModelLen, nullptr, 0) == -1)
return Err(OsError::withErrno("Failed to get host info"));
// taken from https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/host/host_mac.c // taken from https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/host/host_mac.c
// shortened a lot of the entries to remove unnecessary info // shortened a lot of the entries to remove unnecessary info
@ -192,18 +195,22 @@ fn os::GetHost() -> String {
{ "iMac9,1", "iMac (24/20-inch, 2009)" }, { "iMac9,1", "iMac (24/20-inch, 2009)" },
}; };
return String(modelNameByHwModel[hwModel.data()]); const auto it = modelNameByHwModel.find(hwModel.data());
if (it == modelNameByHwModel.end())
return Err(OsError::withErrno("Failed to get host info"));
return String(it->second);
} }
fn os::GetDiskUsage() -> std::pair<u64, u64> { fn os::GetDiskUsage() -> Result<DiskSpace, OsError> {
struct statvfs vfs; struct statvfs vfs;
if (statvfs("/", &vfs) != 0) if (statvfs("/", &vfs) != 0)
return { 0, 0 }; return Err(OsError::withErrno("Failed to get disk usage"));
return { (vfs.f_blocks - vfs.f_bfree) * vfs.f_frsize, vfs.f_blocks * vfs.f_frsize }; return DiskSpace { .used_bytes=(vfs.f_blocks - vfs.f_bfree) * vfs.f_frsize, .total_bytes=vfs.f_blocks * vfs.f_frsize };
} }
fn os::GetShell() -> String { return ""; } fn os::GetShell() -> Option<String> { return None; }
#endif #endif

View file

@ -11,15 +11,15 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface Bridge : NSObject @interface Bridge : NSObject
+ (void)fetchCurrentPlayingMetadata:(void (^)(std::expected<NSDictionary*, const char*>))completion; + (void)fetchCurrentPlayingMetadata:(void (^)(Result<NSDictionary*, const char*>))completion;
+ (std::expected<String, String>)macOSVersion; + (Result<String, OsError>)macOSVersion;
@end @end
#else #else
extern "C++" { extern "C++" {
fn GetCurrentPlayingInfo() -> std::expected<String, NowPlayingError>; fn GetCurrentPlayingInfo() -> Result<MediaInfo, NowPlayingError>;
fn GetMacOSVersion() -> std::expected<String, String>; fn GetMacOSVersion() -> Result<String, OsError>;
} }
#endif #endif

View file

@ -59,7 +59,7 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
); );
} }
+ (std::expected<String, String>)macOSVersion { + (Result<String, OsError>)macOSVersion {
NSProcessInfo* processInfo = [NSProcessInfo processInfo]; NSProcessInfo* processInfo = [NSProcessInfo processInfo];
NSOperatingSystemVersion osVersion = [processInfo operatingSystemVersion]; NSOperatingSystemVersion osVersion = [processInfo operatingSystemVersion];
@ -84,20 +84,21 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
extern "C++" { extern "C++" {
// NOLINTBEGIN(misc-use-internal-linkage) // NOLINTBEGIN(misc-use-internal-linkage)
fn GetCurrentPlayingInfo() -> std::expected<String, NowPlayingError> { fn GetCurrentPlayingInfo() -> Result<MediaInfo, NowPlayingError> {
__block std::expected<String, NowPlayingError> result; __block Result<MediaInfo, NowPlayingError> result;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_semaphore_t const semaphore = dispatch_semaphore_create(0);
[Bridge fetchCurrentPlayingMetadata:^(std::expected<NSDictionary*, const char*> metadataResult) { [Bridge fetchCurrentPlayingMetadata:^(std::expected<NSDictionary*, const char*> metadataResult) {
if (!metadataResult) { if (!metadataResult) {
result = std::unexpected(NowPlayingError { metadataResult.error() }); result = Err(OsError { OsErrorCode::InternalError, metadataResult.error() });
dispatch_semaphore_signal(semaphore); dispatch_semaphore_signal(semaphore);
return; return;
} }
const NSDictionary* const metadata = *metadataResult; const NSDictionary* const metadata = *metadataResult;
if (!metadata) { if (!metadata) {
result = std::unexpected(NowPlayingError { NowPlayingCode::NoPlayers }); result = Err(OsError { OsErrorCode::InternalError, "No metadata" });
dispatch_semaphore_signal(semaphore); dispatch_semaphore_signal(semaphore);
return; return;
} }
@ -105,14 +106,10 @@ extern "C++" {
const NSString* const title = metadata[@"kMRMediaRemoteNowPlayingInfoTitle"]; const NSString* const title = metadata[@"kMRMediaRemoteNowPlayingInfoTitle"];
const NSString* const artist = metadata[@"kMRMediaRemoteNowPlayingInfoArtist"]; const NSString* const artist = metadata[@"kMRMediaRemoteNowPlayingInfoArtist"];
if (!title && !artist) result = MediaInfo(
result = std::unexpected(NowPlayingError { "No metadata" }); title ? Option(String([title UTF8String])) : None,
else if (!title) artist ? Option(String([artist UTF8String])) : None
result = String([artist UTF8String]); );
else if (!artist)
result = String([title UTF8String]);
else
result = String([[NSString stringWithFormat:@"%@ - %@", title, artist] UTF8String]);
dispatch_semaphore_signal(semaphore); dispatch_semaphore_signal(semaphore);
}]; }];
@ -121,7 +118,7 @@ extern "C++" {
return result; return result;
} }
fn GetMacOSVersion() -> std::expected<String, String> { return [Bridge macOSVersion]; } fn GetMacOSVersion() -> Result<String, OsError> { return [Bridge macOSVersion]; }
// NOLINTEND(misc-use-internal-linkage) // NOLINTEND(misc-use-internal-linkage)
} }

View file

@ -1,15 +1,17 @@
#pragma once #pragma once
#include <array> // std::array alias (Array) #include <array> // std::array alias (Array)
#include <cstdlib> // std::getenv, std::free #include <cstdlib> // std::getenv, std::free
#include <expected> // std::expected alias (Result) #include <expected> // std::expected alias (Result)
#include <map> // std::map alias (Map) #include <format> // std::format
#include <memory> // std::shared_ptr and std::unique_ptr aliases (SharedPointer, UniquePointer) #include <map> // std::map alias (Map)
#include <optional> // std::optional alias (Option) #include <memory> // std::shared_ptr and std::unique_ptr aliases (SharedPointer, UniquePointer)
#include <string> // std::string and std::string_view aliases (String, StringView) #include <optional> // std::optional alias (Option)
#include <utility> // std::pair alias (Pair) #include <string> // std::string and std::string_view aliases (String, StringView)
#include <variant> // std::variant alias (NowPlayingError) #include <system_error> // std::error_code and std::system_error
#include <vector> // std::vector alias (Vec) #include <utility> // std::pair alias (Pair)
#include <variant> // std::variant alias (NowPlayingError)
#include <vector> // std::vector alias (Vec)
#ifdef _WIN32 #ifdef _WIN32
#include <winrt/base.h> // winrt::hresult_error (WindowsError) #include <winrt/base.h> // winrt::hresult_error (WindowsError)
@ -230,7 +232,43 @@ struct OsError {
default: code = PlatformSpecific; break; default: code = PlatformSpecific; break;
} }
} }
#endif
static auto withErrno(const String& context) -> OsError {
const i32 errNo = errno;
const String msg = std::system_category().message(errNo);
const String fullMsg = std::format("{}: {}", context, msg);
switch (errNo) {
case EACCES:
case EPERM: return OsError { OsErrorCode::PermissionDenied, fullMsg };
case ENOENT: return OsError { OsErrorCode::NotFound, fullMsg };
case ETIMEDOUT: return OsError { OsErrorCode::Timeout, fullMsg };
case ENOTSUP: return OsError { OsErrorCode::NotSupported, fullMsg };
case EIO: return OsError { OsErrorCode::IoError, fullMsg };
case ECONNREFUSED:
case ENETDOWN:
case ENETUNREACH: return OsError { OsErrorCode::NetworkError, fullMsg };
default: return OsError { OsErrorCode::PlatformSpecific, fullMsg };
}
}
#ifdef __linux__
static auto fromDBus(const DBus::Error& err) -> OsError {
String name = err.name();
if (name == "org.freedesktop.DBus.Error.ServiceUnknown" || name == "org.freedesktop.DBus.Error.NameHasNoOwner")
return OsError { OsErrorCode::NotFound, std::format("DBus service/name not found: {}", err.message()) };
if (name == "org.freedesktop.DBus.Error.NoReply" || name == "org.freedesktop.DBus.Error.Timeout")
return OsError { OsErrorCode::Timeout, std::format("DBus timeout/no reply: {}", err.message()) };
if (name == "org.freedesktop.DBus.Error.AccessDenied")
return OsError { OsErrorCode::PermissionDenied, std::format("DBus access denied: {}", err.message()) };
return OsError { OsErrorCode::PlatformSpecific, std::format("DBus error: {} - {}", name, err.message()) };
}
#endif // __linux__
#endif // _WIN32
}; };
/** /**
@ -252,17 +290,15 @@ struct DiskSpace {
* Using Option<> for fields that might not always be available. * Using Option<> for fields that might not always be available.
*/ */
struct MediaInfo { struct MediaInfo {
/**
* @enum PlaybackStatus
* @brief Represents the playback status of the media player.
*/
enum class PlaybackStatus : u8 { Playing, Paused, Stopped, Unknown };
Option<String> title; ///< Track title. Option<String> title; ///< Track title.
Option<String> artist; ///< Track artist(s). Option<String> artist; ///< Track artist(s).
Option<String> album; ///< Album name. Option<String> album; ///< Album name.
Option<String> app_name; ///< Name of the media player application (e.g., "Spotify", "Firefox"). Option<String> app_name; ///< Name of the media player application (e.g., "Spotify", "Firefox").
PlaybackStatus status = PlaybackStatus::Unknown; ///< Current playback status.
MediaInfo() = default;
MediaInfo(Option<String> title, Option<String> artist)
: title(std::move(title)), artist(std::move(artist)) {}
MediaInfo(Option<String> title, Option<String> artist, Option<String> album, Option<String> app) MediaInfo(Option<String> title, Option<String> artist, Option<String> album, Option<String> app)
: title(std::move(title)), artist(std::move(artist)), album(std::move(album)), app_name(std::move(app)) {} : title(std::move(title)), artist(std::move(artist)), album(std::move(album)), app_name(std::move(app)) {}