-
-
Notifications
You must be signed in to change notification settings - Fork 27
/
osx_api_hook.hh
129 lines (107 loc) · 3.58 KB
/
osx_api_hook.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @file osx_api_hook.hh
* @authors Stavros Avramidis
*/
#pragma once
// cpp libs
#include <chrono>
#include <codecvt>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
// osx api
#include <Carbon/Carbon.h>
/**
* @brier Converts an std::wstring to utr-8 std::string
* @param wstr The wstring to be converted
* @return The copnverted string
*/
std::string rawWstringToString(const std::wstring &wstr) {
return std::string(wstr.begin(), wstr.end());
}
/// @brief Enum describing the state of TIDAL app
enum status { error, closed, opened, playing };
std::wstring ctow(const char *src) {
std::vector<wchar_t> dest(strlen(src) + 1);
int i = mbstowcs(&dest[0], src, strlen(src));
return std::wstring(&dest[0]);
}
/**
* Attempting to get a Stream of the screen triggering the Screen Recording Permission window on macOS Catalina
* @return Bool showing presence of permissions for screen recording
*/
bool macPerms() {
CGDisplayStreamRef stream = CGDisplayStreamCreate(
CGMainDisplayID(),
1,
1,
'BGRA',
nil,
^(CGDisplayStreamFrameStatus status,
uint64_t displayTime,
IOSurfaceRef frameSurface,
CGDisplayStreamUpdateRef updateRef) {}
);
if (stream) {
CFRelease(stream);
return true;
} else {
return false;
}
}
/**
* @brief Checks tidal Info
* @param song Track name if tidal is playing else empty string
* @param artist Artist name if tidal is playing else empty string
* @return returns a <status> struct with current tidal ifno
*/
status tidalInfo(std::wstring &song, std::wstring &artist) {
char buffer[512] = "";
int layer = 0;
status result = closed;
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
CFIndex numWindows = CFArrayGetCount(windowList);
const std::wregex rgx(L"(.+) - (?!\\{)(.+)");
song = L"";
artist = L"";
for (int i = 0; i < (int) numWindows; i++) {
auto info = (CFDictionaryRef) CFArrayGetValueAtIndex(windowList, i);
auto appName = (CFStringRef) CFDictionaryGetValue(info, kCGWindowOwnerName);
CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(info, kCGWindowLayer), kCFNumberIntType, &layer);
if (appName != nullptr) {
CFStringGetCString(appName, buffer, 512, kCFStringEncodingUTF8);
if (layer == 0 && std::strcmp(buffer, "TIDAL") == 0) {
char title[512] = "";
auto windowTitle = (CFStringRef) CFDictionaryGetValue(info, kCGWindowName);
if (windowTitle != nullptr) {
CFStringGetCString(windowTitle, title, sizeof title, kCFStringEncodingUTF8);
result = opened;
std::wsmatch matches;
auto wtitle = std::wstring(title, title + strlen(title));
if (std::regex_search(wtitle, matches, rgx)) {
song = matches[1].str();
artist = matches[2].str();
result = playing;
goto _exit;
}
}
}
}
}
_exit:
return result;
}
/**
* Gets locale of current user
* @return ISO 2 letter formated country code
*/
inline char *getLocale() noexcept {
char *tmp = new char[2];
auto localeID = (CFStringRef) CFLocaleGetValue(CFLocaleCopyCurrent(), kCFLocaleCountryCode);
CFStringGetCString(localeID, tmp, 16, kCFStringEncodingUTF8);
return tmp;
}