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 "src/util/types.h"
fn os::GetMemInfo() -> Result<u64, String> {
fn os::GetMemInfo() -> Result<u64, OsError> {
u64 mem = 0;
usize size = sizeof(mem);
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;
}
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::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 {};
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();
}
fn os::GetHost() -> String {
fn os::GetHost() -> Result<String, OsError> {
std::array<char, 256> 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
// 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)" },
};
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;
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

View file

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

View file

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

View file

@ -3,10 +3,12 @@
#include <array> // std::array alias (Array)
#include <cstdlib> // std::getenv, std::free
#include <expected> // std::expected alias (Result)
#include <format> // std::format
#include <map> // std::map alias (Map)
#include <memory> // std::shared_ptr and std::unique_ptr aliases (SharedPointer, UniquePointer)
#include <optional> // std::optional alias (Option)
#include <string> // std::string and std::string_view aliases (String, StringView)
#include <system_error> // std::error_code and std::system_error
#include <utility> // std::pair alias (Pair)
#include <variant> // std::variant alias (NowPlayingError)
#include <vector> // std::vector alias (Vec)
@ -230,7 +232,43 @@ struct OsError {
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.
*/
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> artist; ///< Track artist(s).
Option<String> album; ///< Album name.
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)
: title(std::move(title)), artist(std::move(artist)), album(std::move(album)), app_name(std::move(app)) {}