This commit is contained in:
Mars 2025-05-10 14:02:49 -04:00
parent 8809421181
commit 3c154878d3
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
4 changed files with 79 additions and 42 deletions

View file

@ -142,7 +142,7 @@ namespace {
if (getsockopt(fileDescriptor, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
return Err(DracError("Failed to get socket credentials (SO_PEERCRED)"));
Array<char, 128> exeLinkPathBuf;
Array<char, 128> exeLinkPathBuf {};
auto [out, size] = std::format_to_n(exeLinkPathBuf.data(), exeLinkPathBuf.size() - 1, "/proc/{}/exe", cred.pid);
@ -153,7 +153,7 @@ namespace {
const char* exeLinkPath = exeLinkPathBuf.data();
Array<char, PATH_MAX> exeRealPathBuf; // NOLINT(misc-include-cleaner) - PATH_MAX is in <climits>
Array<char, PATH_MAX> exeRealPathBuf {}; // NOLINT(misc-include-cleaner) - PATH_MAX is in <climits>
const isize bytesRead = readlink(exeLinkPath, exeRealPathBuf.data(), exeRealPathBuf.size() - 1);

View file

@ -1,9 +1,9 @@
#ifdef __APPLE__
// clang-format off
#include <flat_map>
#include <sys/statvfs.h>
#include <sys/sysctl.h>
#include <flat_map> // std::flat_map
#include <sys/statvfs.h> // statvfs
#include <sys/sysctl.h> // {CTL_KERN, KERN_PROC, KERN_PROC_ALL, kinfo_proc, sysctl, sysctlbyname}
#include "src/core/package.hpp"
#include "src/util/defs.hpp"
@ -292,8 +292,10 @@ namespace os {
if (statvfs("/", &vfs) != 0)
return Err(DracError("Failed to get disk usage"));
return DiskSpace { .usedBytes = (vfs.f_blocks - vfs.f_bfree) * vfs.f_frsize,
.totalBytes = vfs.f_blocks * vfs.f_frsize };
return DiskSpace {
.usedBytes = (vfs.f_blocks - vfs.f_bfree) * vfs.f_frsize,
.totalBytes = vfs.f_blocks * vfs.f_frsize,
};
}
fn GetShell() -> Result<String> {

View file

@ -7,15 +7,16 @@
#include "src/util/error.hpp"
#include "src/util/types.hpp"
// clang-format on
using util::error::DracError;
using util::types::MediaInfo, util::types::String, util::types::Result;
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <Foundation/Foundation.h> // Foundation
@interface Bridge : NSObject
+ (void)fetchCurrentPlayingMetadata:(void (^)(Result<NSDictionary*, const char*>))completion;
+ (Result<String, DracError>)macOSVersion;
+ (void)fetchCurrentPlayingMetadata:(void (^_Nonnull)(NSDictionary* __nullable, NSError* __nullable))completion;
+ (NSString* __nullable)macOSVersion;
@end
#else
extern "C++" {

View file

@ -4,30 +4,34 @@
#import "bridge.hpp"
#import <dispatch/dispatch.h>
#import <objc/runtime.h>
#include <expected>
#include <functional>
#include <memory>
#import <objc/runtime.h>
#include <string>
#include <utility>
#include "src/util/error.hpp"
// clang-format on
using util::error::DracErrorCode;
using util::types::Err, util::types::Option, util::types::None;
using util::error::DracError, util::error::DracErrorCode;
using util::types::Err, util::types::Option, util::types::None, util::types::Result;
using MRMediaRemoteGetNowPlayingInfoFunction =
void (*)(dispatch_queue_t queue, void (^handler)(NSDictionary* information));
@implementation Bridge
+ (void)fetchCurrentPlayingMetadata:(void (^)(std::expected<NSDictionary*, const char*>))completion {
+ (void)fetchCurrentPlayingMetadata:(void (^)(NSDictionary* __nullable, NSError* __nullable))completion {
CFURLRef urlRef = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault, CFSTR("/System/Library/PrivateFrameworks/MediaRemote.framework"), kCFURLPOSIXPathStyle, false
kCFAllocatorDefault,
CFSTR("/System/Library/PrivateFrameworks/MediaRemote.framework"),
kCFURLPOSIXPathStyle,
false
);
if (!urlRef) {
completion(std::unexpected("Failed to create CFURL for MediaRemote framework"));
completion(nil, [NSError errorWithDomain:@"com.draconis.error" code:1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed to create CFURL for MediaRemote framework" }]);
return;
}
@ -36,7 +40,7 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
CFRelease(urlRef);
if (!bundleRef) {
completion(std::unexpected("Failed to create bundle for MediaRemote framework"));
completion(nil, [NSError errorWithDomain:@"com.draconis.error" code:1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed to create bundle for MediaRemote framework" }]);
return;
}
@ -46,7 +50,7 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
if (!mrMediaRemoteGetNowPlayingInfo) {
CFRelease(bundleRef);
completion(std::unexpected("Failed to get MRMediaRemoteGetNowPlayingInfo function pointer"));
completion(nil, [NSError errorWithDomain:@"com.draconis.error" code:1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed to get MRMediaRemoteGetNowPlayingInfo function pointer" }]);
return;
}
@ -58,34 +62,54 @@ using MRMediaRemoteGetNowPlayingInfoFunction =
mrMediaRemoteGetNowPlayingInfo(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(NSDictionary* information) {
completion(
information ? std::expected<NSDictionary*, const char*>(information)
: std::unexpected("No now playing information")
);
if (!information) {
completion(nil, [NSError errorWithDomain:@"com.draconis.error" code:1 userInfo:@ { NSLocalizedDescriptionKey : @"No now playing information" }]);
return;
}
completion(information, nil);
}
);
}
+ (Result<String>)macOSVersion {
+ (NSString*)macOSVersion {
NSProcessInfo* processInfo = [NSProcessInfo processInfo];
if (!processInfo)
return nil;
NSOperatingSystemVersion osVersion = [processInfo operatingSystemVersion];
if (osVersion.majorVersion == 0)
return nil;
NSString* versionNumber = nil;
if (osVersion.patchVersion == 0) {
versionNumber = [NSString stringWithFormat:@"%ld.%ld", osVersion.majorVersion, osVersion.minorVersion];
} else {
versionNumber = [NSString
stringWithFormat:@"%ld.%ld.%ld", osVersion.majorVersion, osVersion.minorVersion, osVersion.patchVersion];
}
if (osVersion.patchVersion == 0)
versionNumber = [NSString stringWithFormat:@"%ld.%ld",
osVersion.majorVersion,
osVersion.minorVersion];
else
versionNumber = [NSString stringWithFormat:@"%ld.%ld.%ld",
osVersion.majorVersion,
osVersion.minorVersion,
osVersion.patchVersion];
if (!versionNumber)
return nil;
NSDictionary* versionNames =
@{ @11 : @"Big Sur", @12 : @"Monterey", @13 : @"Ventura", @14 : @"Sonoma", @15 : @"Sequoia" };
@{
@11 : @"Big Sur",
@12 : @"Monterey",
@13 : @"Ventura",
@14 : @"Sonoma",
@15 : @"Sequoia"
};
NSNumber* majorVersion = @(osVersion.majorVersion);
NSString* versionName = versionNames[majorVersion] ? versionNames[majorVersion] : @"Unknown";
NSString* fullVersion = [NSString stringWithFormat:@"macOS %@ %@", versionNumber, versionName];
return String([fullVersion UTF8String]);
return fullVersion ? fullVersion : nil;
}
@end
@ -96,25 +120,29 @@ extern "C++" {
const dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[Bridge fetchCurrentPlayingMetadata:^(std::expected<NSDictionary*, const char*> metadataResult) {
if (!metadataResult) {
result = Err(DracError(DracErrorCode::InternalError, metadataResult.error()));
[Bridge fetchCurrentPlayingMetadata:^(NSDictionary* __nullable information, NSError* __nullable error) {
if (error) {
result = Err(DracError(DracErrorCode::InternalError, [error.localizedDescription UTF8String]));
dispatch_semaphore_signal(semaphore);
return;
}
const NSDictionary* const metadata = *metadataResult;
if (!metadata) {
if (!information) {
result = Err(DracError(DracErrorCode::InternalError, "No metadata"));
dispatch_semaphore_signal(semaphore);
return;
}
const NSString* const title = metadata[@"kMRMediaRemoteNowPlayingInfoTitle"];
const NSString* const artist = metadata[@"kMRMediaRemoteNowPlayingInfoArtist"];
const NSString* const title = information[@"kMRMediaRemoteNowPlayingInfoTitle"];
const NSString* const artist = information[@"kMRMediaRemoteNowPlayingInfoArtist"];
result = MediaInfo(
title ? Option(String([title UTF8String])) : None, artist ? Option(String([artist UTF8String])) : None
title
? Option(String([title UTF8String]))
: None,
artist
? Option(String([artist UTF8String]))
: None
);
dispatch_semaphore_signal(semaphore);
@ -124,7 +152,13 @@ extern "C++" {
return result;
}
fn GetMacOSVersion() -> Result<String> { return [Bridge macOSVersion]; }
fn GetMacOSVersion() -> Result<String> {
NSString* version = [Bridge macOSVersion];
return version
? Result<String>(String([version UTF8String]))
: Err(DracError(DracErrorCode::InternalError, "Failed to get macOS version"));
}
// NOLINTEND(misc-use-internal-linkage)
}