Skip to content

Commit

Permalink
Add hacky push-to-talk support.
Browse files Browse the repository at this point in the history
Because Wayland forbids processes from listening to system-wide
keypresses, Discord and WebCord are unable to listen for a push-to-talk
key. This commit hacks onto WebCord's socket server and allows for
sending a payload to activate and deactivate push-to-talk. The delay
between sending the packet and push-to-talk state changing appears to be
low enough for daily use. You could activate push-to-talk like so:

`echo '{"pttAction": "activate"}' | websocat --origin https://127.0.0.1 ws://127.0.0.1:6463`

The two "actions" that are supported are `activate` and `deactivate`.

The "hack" part of this commit also refers to the activation method -
the F12 key is used to trigger push-to-talk. Make sure that F12 is bound
before triggering actions, otherwise nothing will happen.
  • Loading branch information
epetousis committed Sep 9, 2022
1 parent 6d6e033 commit e6c05a0
Showing 1 changed file with 28 additions and 4 deletions.
32 changes: 28 additions & 4 deletions sources/code/main/modules/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,13 @@ export default async function startServer(window:Electron.BrowserWindow) {
const trust = {
isKnown: knownIstancesList.filter(instance => instance[1].origin === origin).length === 0,
isDiscordService: /^https:\/\/[a-z]+\.discord\.com$/.test(origin),
isLocal: "http://127.0.0.1"
isLocal: /^https?:\/\/127.0.0.1/.test(origin)
};
if(!trust.isKnown && !trust.isDiscordService && !trust.isLocal) {
console.debug("[WSS] Blocked request from origin '"+origin+"'. (not trusted)");
return wss.close(1008,"Client is not trusted.");
}
if(trust.isDiscordService || trust.isLocal) {
if(trust.isDiscordService) {
console.debug("[WSS] Blocked request from origin '"+origin+"'. (not supported)");
return wss.close(1008,"Client is not supported.");
}
Expand All @@ -177,8 +177,32 @@ export default async function startServer(window:Electron.BrowserWindow) {
parsedData = (data as Buffer).toString();
if(isJsonSyntaxCorrect(parsedData as string))
parsedData = JSON.parse(parsedData as string);
if ('pttAction' in (parsedData as Record<string, string>)
&& typeof (parsedData as Record<string, string>)['pttAction'] === 'string'
&& trust.isLocal) {
const pttData = parsedData as Record<string, string>;
// Handle push to talk actions here
switch (pttData['pttAction']) {
case 'activate':
console.debug('[WS] Handling PTT activation action.');
// Unfortunately, Discord has trouble handling F keys greater than 12.
// Using an accelerator with modifiers seems to also break PTT.
window.webContents.sendInputEvent({type: 'keyDown', keyCode: 'F12'});
break;
case 'deactivate':
console.debug('[WS] Handling PTT deactivation action.');
window.webContents.sendInputEvent({type: 'keyUp', keyCode: 'F12'});
break;
case 'toggle':
console.debug('[WS] Handling PTT deactivation action.');
window.webContents.sendInputEvent({type: 'keyUp', keyCode: 'F12'});
break;
default:
console.debug('Unexpected PTT action was received on WSS.');
}
}
// Invite response handling
if(isResponse(parsedData, ["INVITE_BROWSER", "GUILD_TEMPLATE_BROWSER"] as ("INVITE_BROWSER"|"GUILD_TEMPLATE_BROWSER")[])) {
else if(isResponse(parsedData, ["INVITE_BROWSER", "GUILD_TEMPLATE_BROWSER"] as ("INVITE_BROWSER"|"GUILD_TEMPLATE_BROWSER")[])) {
if(lock) {
console.debug('[WSS] Blocked request "'+parsedData.cmd+'" (WSS locked).');
return wss.close(1013,"Server is busy, try again later.");
Expand Down Expand Up @@ -258,4 +282,4 @@ export default async function startServer(window:Electron.BrowserWindow) {
}
});
});
}
}

9 comments on commit e6c05a0

@Shinyzenith
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking for this actually, cool to see you hacked it in ahaha. Now I can use push to talk with swhkd.

@epetousis
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny coincidence, I literally just came across swhkd as a way to get this working, since Gnome shortcuts aren't quite the right solution. swhkd would be perfect for my setup if it had mouse bind support, but the fact that it exists as-is is a godsend.

@Shinyzenith
Copy link

@Shinyzenith Shinyzenith commented on e6c05a0 Sep 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤣 your profile showed up on our internal webhook (star) and that led me here. I'm working on experimental mouse support but I must mention that the patch is still in heavy development 😁.

@SpacingBat3
Copy link
Owner

@SpacingBat3 SpacingBat3 commented on e6c05a0 Sep 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shinyzenith @epetousis I think throught it would be better to use Electron API (i.e. global shortcuts) that should be supported across all platforms and work out-of-the-box when configured/set in WebCord. If that is not the case for Wayland, at least regular UNIX socket should be used for e.g. security reasons (WebSockets are also available to websites, where UNIX sockets shouldn't be). Probably packets could also be smaller when properly encoded (not as text, binary data can be represented by JS, AFAIK as part of ECMAScript specifications, with ArrayBuffers or Buffers in case of Node.js).

@epetousis
Copy link
Author

@epetousis epetousis commented on e6c05a0 Sep 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SpacingBat3 this hack was literally just something I whipped up in an hour to get feature parity from Windows Discord, so I figured there would be a better way to go about it. Appreciate you commenting on this.

I agree that the global shortcuts API should be the best way to go about this, but trying to use this API in Wayland simply fails. After taking a look, global Wayland shortcuts seem to be entirely unimplemented in Chromium's codebase, likely due to the aforementioned limitations on Wayland. So this API is unfortunately a non-starter, and I think all that can be done for now is a method of communicating with WebCord to trigger shortcuts manually.

Also agree that this should be using UNIX sockets or even D-Bus rather than websockets. Ideally, I'd like to get a solution that works with all Discord shortcuts implemented and merged into WebCord, but I'd need to research Discord's shortcut mechanism a bit more.

@SpacingBat3
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@epetousis You can also research a bit of WebCord's code, mostly the preload script of the main window (sources/code/renderer/preload/main.ts), it shows the way to actually access and modify the Discord's localStorage before Discord will remove access to it... You can find there the binded key for push-to-talk, so it won't have to be hard-coded (ideally, key press would just be passed to Discord with the global shortcuts for those who support it and probably use UNIX socket in other cases).

I may work on global push-to-talk for non-Wayland users if I'll have a time for that.

@Shinyzenith
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SpacingBat3 hi! As epetousis already mentioned, this isn't a proper implementation but just a hack we're trying out. I believe there's an official xdg portal spec being made for global hotkeys, once that's out you can properly have global hotkeys on linux ( maybe with a os check in the source code ? This impl won't depend on wlroots / gnome / kde specific code )

@epetousis
Copy link
Author

@epetousis epetousis commented on e6c05a0 Sep 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shinyzenith if I'm reading the comments on that spec issue correctly (this one, right?), it's not quite clear whether push-to-talk-style shortcuts are going to be implemented as part of it. Would be great if it did, though.

@Shinyzenith
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! that's the protocol spec I'm talking about. I haven't looked too deep into it so you're probably correct.
I guess we'll find out when the api is finalized. Worst case scenario, I'll propose changes upstream because this is a really basic functionality for the modern desktop.

Please sign in to comment.