ok well it . compiles and runs so
This commit is contained in:
parent
350e3a13db
commit
b534cbddb0
4 changed files with 91 additions and 51 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)) {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue