Add callscreen DWM plugin for incoming and active voice calls
This commit is contained in:
@@ -631,16 +631,20 @@ int calllog_plugin_init(const DwmHostApi* host) {
|
||||
int calllog_on_global_key(const DwmHostApi* host, KeySym keysym,
|
||||
unsigned int keycode, unsigned int state,
|
||||
int is_press) {
|
||||
(void)host;
|
||||
if (!is_press || state != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (keysym == XF86XK_Phone || keysym == XF86XK_PickupPhone || keycode == 177) {
|
||||
if (isCallRingingFast()) {
|
||||
const char* const argv[] = {"sxmo_hook_pickup.sh", nullptr};
|
||||
if (host && host->spawn_command) {
|
||||
host->spawn_command(argv);
|
||||
} else {
|
||||
runAsyncArgv("sxmo_hook_pickup.sh");
|
||||
if (!sendPluginCommand("callscreen", "ACCEPT")) {
|
||||
runAsyncArgv("xcallscreen", "accept");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (isCallActiveOrRingingFast()) {
|
||||
if (!sendPluginCommand("callscreen", "OPEN")) {
|
||||
runAsyncArgv("xcallscreen");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -655,9 +659,14 @@ int calllog_on_idle_key(const DwmHostApi* host, KeySym keysym,
|
||||
}
|
||||
if (keysym == XF86XK_Phone || keysym == XF86XK_PickupPhone || keycode == 177) {
|
||||
if (isCallRingingFast()) {
|
||||
const char* const argv[] = {"sxmo_hook_pickup.sh", nullptr};
|
||||
if (host->spawn_command) {
|
||||
host->spawn_command(argv);
|
||||
if (!sendPluginCommand("callscreen", "ACCEPT")) {
|
||||
runAsyncArgv("xcallscreen", "accept");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (isCallActiveOrRingingFast()) {
|
||||
if (!sendPluginCommand("callscreen", "OPEN")) {
|
||||
runAsyncArgv("xcallscreen");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -160,6 +160,39 @@ static int try_send_plugin_fifo(const char *plugin_name, int sub_argc, char **su
|
||||
} else if (strcmp(plugin_name, "dmenu") == 0 && sub_argc >= 2 && sub_argv[1] &&
|
||||
strcmp(sub_argv[1], "close") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "CLOSE\n");
|
||||
} else if (strcmp(plugin_name, "callscreen") == 0) {
|
||||
if (sub_argc >= 2 && sub_argv[1] && sub_argv[1][0]) {
|
||||
const char *verb = sub_argv[1];
|
||||
const char *a1 = (sub_argc >= 3 && sub_argv[2]) ? sub_argv[2] : "";
|
||||
const char *a2 = (sub_argc >= 4 && sub_argv[3]) ? sub_argv[3] : "";
|
||||
if (strcasecmp(verb, "incoming") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "INCOMING %s %s\n", a1[0] ? a1 : "-", a2);
|
||||
} else if (strcasecmp(verb, "outgoing") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "OUTGOING %s %s\n", a1[0] ? a1 : "-", a2);
|
||||
} else if (strcasecmp(verb, "active") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "ACTIVE %s %s\n", a1[0] ? a1 : "-", a2);
|
||||
} else if (strcasecmp(verb, "accept") == 0 || strcasecmp(verb, "pickup") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "ACCEPT\n");
|
||||
} else if (strcasecmp(verb, "hangup") == 0 || strcasecmp(verb, "reject") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "HANGUP\n");
|
||||
} else if (strcasecmp(verb, "mute") == 0 || strcasecmp(verb, "mute_ring") == 0 ||
|
||||
strcasecmp(verb, "ignore") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "MUTE_RING\n");
|
||||
} else if (strcasecmp(verb, "ended") == 0 || strcasecmp(verb, "end") == 0) {
|
||||
len = a1[0] ? snprintf(cmd, sizeof(cmd), "ENDED %s\n", a1)
|
||||
: snprintf(cmd, sizeof(cmd), "ENDED\n");
|
||||
} else if (strcasecmp(verb, "close") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "CLOSE\n");
|
||||
} else if (strcasecmp(verb, "record") == 0 || strcasecmp(verb, "toggle_rec") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "TOGGLE_REC\n");
|
||||
} else if (strcasecmp(verb, "mic") == 0 || strcasecmp(verb, "toggle_mic") == 0) {
|
||||
len = snprintf(cmd, sizeof(cmd), "TOGGLE_MIC\n");
|
||||
} else {
|
||||
len = snprintf(cmd, sizeof(cmd), "OPEN %s\n", verb);
|
||||
}
|
||||
} else {
|
||||
len = snprintf(cmd, sizeof(cmd), "OPEN\n");
|
||||
}
|
||||
} else if (sub_argc >= 2 && sub_argv[1] && strcmp(sub_argv[1], "newcontact") == 0) {
|
||||
const char *num = (sub_argc >= 3 && sub_argv[2]) ? sub_argv[2] : "";
|
||||
len = snprintf(cmd, sizeof(cmd), "OPEN new:%s\n", num);
|
||||
@@ -203,6 +236,9 @@ static const char *resolve_plugin_name_from_argv0(const char *argv0) {
|
||||
if (strcasecmp(base, "xcalllog") == 0 || strcasecmp(base, "calllog") == 0) {
|
||||
return "calllog";
|
||||
}
|
||||
if (strcasecmp(base, "xcallscreen") == 0 || strcasecmp(base, "callscreen") == 0) {
|
||||
return "callscreen";
|
||||
}
|
||||
if (strcasecmp(base, "xcontacts") == 0 || strcasecmp(base, "contacts") == 0) {
|
||||
return "contacts";
|
||||
}
|
||||
|
||||
@@ -72,6 +72,12 @@ constexpr const char* kIconRefresh = "\xef\x80\xa1"; // U+F021 refresh
|
||||
constexpr const char* kIconSort = "\xef\x83\x9c"; // U+F0DC sort
|
||||
constexpr const char* kIconEye = "\xef\x81\xae"; // U+F06E eye/view
|
||||
constexpr const char* kIconPalette = "\xef\x87\xbc"; // U+F1FC paint-brush / theme
|
||||
constexpr const char* kIconSpeaker = "\xef\x80\xa8"; // U+F028 speaker
|
||||
constexpr const char* kIconEarpiece = "\xef\x8a\xa0"; // U+F2A0 earpiece
|
||||
constexpr const char* kIconSoundOff = "\xef\x91\xa6"; // U+F466 mute
|
||||
constexpr const char* kIconMicOn = "\xf3\xb0\x8d\xac"; // U+F036C mic on
|
||||
constexpr const char* kIconMicOff = "\xf3\xb0\x8d\xad"; // U+F036D mic off
|
||||
constexpr const char* kIconRecord = "\xef\x84\x91"; // U+F111 circle / record dot
|
||||
|
||||
inline int64_t nowMs() {
|
||||
struct timespec ts {};
|
||||
@@ -211,7 +217,37 @@ inline bool isCallRingingFast() {
|
||||
}
|
||||
std::string ringPidFile = getRuntimeFile("sxmo.ring.pid");
|
||||
int pid = readIntFile(ringPidFile, -1);
|
||||
return (pid > 0 && ::kill(pid, 0) == 0);
|
||||
if (pid > 0 && ::kill(pid, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
if (::access("/tmp/sxmo_call_ringing", F_OK) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isCallActiveOrRingingFast() {
|
||||
if (isCallRingingFast()) {
|
||||
return true;
|
||||
}
|
||||
if (::access("/tmp/sxmo_active_call", F_OK) == 0) {
|
||||
return true;
|
||||
}
|
||||
std::string callsDir = getRuntimeFile("sxmo_calls");
|
||||
DIR* d = ::opendir(callsDir.c_str());
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
bool found = false;
|
||||
struct dirent* ent;
|
||||
while ((ent = ::readdir(d)) != nullptr) {
|
||||
if (ent->d_name[0] != '.' && ent->d_name[0] != '\0') {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
::closedir(d);
|
||||
return found;
|
||||
}
|
||||
|
||||
struct FileStamp {
|
||||
@@ -299,7 +335,8 @@ inline void runAsyncCmd(const std::string& cmd) {
|
||||
|
||||
inline void runAsyncArgv(const char* prog,
|
||||
const char* arg1 = nullptr,
|
||||
const char* arg2 = nullptr) {
|
||||
const char* arg2 = nullptr,
|
||||
const char* arg3 = nullptr) {
|
||||
pid_t pid = ::fork();
|
||||
if (pid == 0) {
|
||||
::setsid();
|
||||
@@ -312,7 +349,13 @@ inline void runAsyncArgv(const char* prog,
|
||||
::close(nullfd);
|
||||
}
|
||||
}
|
||||
if (arg1 && arg2) {
|
||||
if (arg1 && arg2 && arg3) {
|
||||
execlp(prog, prog, arg1, arg2, arg3, static_cast<char*>(nullptr));
|
||||
std::string localBin = std::string("/home/user/.local/bin/") + prog;
|
||||
execl(localBin.c_str(), prog, arg1, arg2, arg3, static_cast<char*>(nullptr));
|
||||
std::string usrBin = std::string("/usr/bin/") + prog;
|
||||
execl(usrBin.c_str(), prog, arg1, arg2, arg3, static_cast<char*>(nullptr));
|
||||
} else if (arg1 && arg2) {
|
||||
execlp(prog, prog, arg1, arg2, static_cast<char*>(nullptr));
|
||||
std::string localBin = std::string("/home/user/.local/bin/") + prog;
|
||||
execl(localBin.c_str(), prog, arg1, arg2, static_cast<char*>(nullptr));
|
||||
@@ -949,6 +992,9 @@ inline void placePhoneCall(const std::string& rawNumber) {
|
||||
if (num.empty()) {
|
||||
return;
|
||||
}
|
||||
if (!sendPluginCommand("callscreen", "OUTGOING - " + num)) {
|
||||
runAsyncArgv("xcallscreen", "outgoing", "-", num.c_str());
|
||||
}
|
||||
runAsyncArgv("sxmo_modemdial.sh", num.c_str());
|
||||
}
|
||||
|
||||
@@ -961,6 +1007,7 @@ inline void closeOtherPlugins(const char* selfPluginName) {
|
||||
{"xdrawer.pid", "xdrawer"},
|
||||
{"xdialer.pid", "dialer"},
|
||||
{"xcalllog.pid", "calllog"},
|
||||
{"xcallscreen.pid", "callscreen"},
|
||||
{"xcontacts.pid", "contacts"},
|
||||
{"xsms.pid", "sms"},
|
||||
{"xfiles.pid", "files"},
|
||||
@@ -986,6 +1033,7 @@ inline void broadcastThemeReload(const char* selfPluginName = nullptr) {
|
||||
"xdrawer",
|
||||
"dialer",
|
||||
"calllog",
|
||||
"callscreen",
|
||||
"contacts",
|
||||
"sms",
|
||||
"files",
|
||||
|
||||
Reference in New Issue
Block a user