Skip to content

Commit

Permalink
Add extension and native code
Browse files Browse the repository at this point in the history
  • Loading branch information
IceDBorn committed Apr 1, 2023
1 parent 2b91288 commit 0d7390e
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 0 deletions.
25 changes: 25 additions & 0 deletions extension/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
function onResponse(response) {
let dropdown = document.getElementById('dropdown');

let allDesktopAudioOption = document.createElement('option');
let allDesktopAudioText = 'All Desktop Audio';
allDesktopAudioOption.innerHTML = allDesktopAudioText;
allDesktopAudioOption.value = allDesktopAudioText;
dropdown.appendChild(allDesktopAudioOption);

for (const element of response) {
let option = document.createElement('option');
option.innerHTML = element;
option.value = element;
dropdown.appendChild(option);
}
}

function onError(error) {
console.error(error)
}

//let sending = browser.runtime.sendNativeMessage("screenAudioMicConnector", { cmd: "StartVirtmic", args: [{ node: '' }] });
//let sending = browser.runtime.sendNativeMessage("screenAudioMicConnector", { cmd: "StopVirtmic", args: [{ micPid: 0 }] });
let sending = browser.runtime.sendNativeMessage("screenAudioMicConnector", { cmd: "GetNodes", args:[]} );
sending.then(onResponse, onError);
Binary file added extension/icons/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions extension/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
function overrideGdm() {
navigator.mediaDevices.chromiumGetDisplayMedia = navigator.mediaDevices.getDisplayMedia;

const getAudioDevice = async (nameOfAudioDevice) => {
await navigator.mediaDevices.getUserMedia({
audio: true
});
await new Promise(r => setTimeout(r, 1000));
let devices = await navigator.mediaDevices.enumerateDevices();
let audioDevice = devices.find(({
label
}) => label === nameOfAudioDevice);
return audioDevice;
};

const getDisplayMedia = async () => {
var id;
try {
let myDiscordAudioSink = await getAudioDevice('screenaudio-mic');
id = myDiscordAudioSink.deviceId;
}
catch (error) {
id = "default";
}
let captureSystemAudioStream = await navigator.mediaDevices.getUserMedia({
audio: {
// We add our audio constraints here, to get a list of supported constraints use navigator.mediaDevices.getSupportedConstraints();
// We must capture a microphone, we use default since its the only deviceId that is the same for every Chromium user
deviceId: {
exact: id
},
// We want auto gain control, noise cancellation and noise suppression disabled so that our stream won't sound bad
autoGainControl: false,
echoCancellation: false,
noiseSuppression: false
// By default Chromium sets channel count for audio devices to 1, we want it to be stereo in case we find a way for Discord to accept stereo screenshare too
//channelCount: 2,
// You can set more audio constraints here, bellow are some examples
//latency: 0,
//sampleRate: 48000,
//sampleSize: 16,
//volume: 1.0
}
});
let [track] = captureSystemAudioStream.getAudioTracks();
const gdm = await navigator.mediaDevices.chromiumGetDisplayMedia({
video: true,
audio: true
});
gdm.addTrack(track);
return gdm;
};

navigator.mediaDevices.getDisplayMedia = getDisplayMedia;
}

const newScript = document.createElement('script')
newScript.innerHTML = `${overrideGdm.toString()}; overrideGdm();`.replaceAll('overrideGdm', '__overrideGdm')
document.body.appendChild(newScript)
38 changes: 38 additions & 0 deletions extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{

"manifest_version": 3,
"name": "screenaudio-mic",
"version": "1.0",

"description": "Passthrough pipewire audio to WebRTC screenshare",

"browser_specific_settings": {
"gecko": {
"id": "screenaudio-mic@icedborn"
}
},

"action": {
"default_popup": "popup.html"
},

"icons": {
"48": "icons/icon.png"
},

"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["index.js"]
}
],

"background": {
"scripts": ["background.js"]
},

"permissions": [
"nativeMessaging"
]

}
14 changes: 14 additions & 0 deletions extension/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Screenaudio Mic</title>
</head>
<body style="background: #202324; color: #e8e6e3;">
<div>
<h3 style="text-align: center;">Select audio node to share</h3>
<select style="background: #202324; color: #e8e6e3;" id="dropdown"></select>
<button style="background: #202324; color: #e8e6e3;" onclick="">Share</button>
</div>
</body>
<script src="background.js"></script>
</html>
File renamed without changes.
File renamed without changes.
34 changes: 34 additions & 0 deletions native/message-parser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {
size_t INT_SIZE = sizeof(int);
unsigned char* buffer;

buffer = (unsigned char*)malloc(INT_SIZE);
for (int i = 0; i < INT_SIZE; i++)
buffer[i] = getchar();

/*
for (int i = 0; i < INT_SIZE / 2; i++) {
unsigned char temp = buffer[i];
buffer[i] = buffer[INT_SIZE - 1 - i];
buffer[INT_SIZE - 1 - i] = temp;
}
*/

int charactersToRead = *(int*)buffer;
// printf("charactersToRead: %d", charactersToRead);
free(buffer);

buffer = (unsigned char*)malloc(charactersToRead + 1);
buffer[charactersToRead] = '\0';
for (int i = 0; i < charactersToRead; i++)
buffer[i] = getchar();

printf("%s", buffer);
free(buffer);

return 0;
}

9 changes: 9 additions & 0 deletions native/native-messaging-hosts/screenAudioMicConnector.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "screenAudioMicConnector",
"description": "Connector to communicate with the browser",
"path": "/home/icedborn/dev/screenaudio-mic/native/screenAudioMicConnector",
"type": "stdio",
"allowed_extensions": [
"screenaudio-mic@icedborn"
]
}
65 changes: 65 additions & 0 deletions native/screenAudioMicConnector
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env bash

export LANG=C
projectRoot="$( cd -- "$(dirname "$0")" > /dev/null 2>&1 ; pwd -P )"

function intToHex () {
printf '%08x' $1 |
sed 's/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\7\8\n\5\6\n\3\4\n\1\2/'
}

function toMessage () {
local message="$1"
local messageLength=`printf "$message" | wc -c`
local messageLengthHex=`intToHex "$messageLength"`

printf "$messageLengthHex\n" | while IFS= read -r line; do
sh -c "printf '\\x$line'"
done

printf "$message"
}

function GetNodes () {
local nodes=`pw-cli ls Node | grep node.name | awk '{print $3}' | sort | uniq | sed 's|\"||g' | jq -R . | jq -s . | jq -c`
toMessage "$nodes"
exit
}

function StartVirtmic () {
local args="$1"
local node=`echo $args | jq -r '.[].node' | head -n 1`

echo $node | nohup ~/git/screenaudio-mic/build/screenaudio-mic > /dev/null &
local micPid=$!

toMessage '{"micPid":'$micPid'}'

exit
}

function StopVirtmic () {
local args="$1"
local micPid=`echo $args | jq '.[].micPid' | head -n 1`

kill "$micPid" && toMessage '{"success":true}' && exit

toMessage '{"success":false}'
exit
}

payload=`$projectRoot/a.out`
cmd=`echo "$payload" | jq -r .cmd`
args=`echo "$payload" | jq .args`

case $cmd in
'GetNodes')
GetNodes "$args"
;;
'StartVirtmic')
StartVirtmic "$args"
;;
'StopVirtmic')
StopVirtmic "$args"
;;
esac

0 comments on commit 0d7390e

Please sign in to comment.