2022-07-09 20:07:14 +00:00
// From v0.4
2022-07-07 11:11:51 +00:00
navigator . mediaDevices . chromiumGetDisplayMedia =
navigator . mediaDevices . getDisplayMedia ;
2022-08-01 20:26:44 +00:00
function sleep ( ms ) {
return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
}
2022-07-07 11:11:51 +00:00
const getAudioDevice = async ( nameOfAudioDevice ) => {
await navigator . mediaDevices . getUserMedia ( {
audio : true ,
} ) ;
2022-08-02 09:56:08 +00:00
let audioDevice ;
while ( audioDevice === undefined ) {
let devices = await navigator . mediaDevices . enumerateDevices ( ) ;
audioDevice = devices . find ( ( { label } ) => label === nameOfAudioDevice ) ;
if ( ! audioDevice )
2022-08-02 10:41:32 +00:00
console . log (
` dsa: Did not find ' ${ nameOfAudioDevice } ', trying again in 100ms `
) ;
2022-08-02 09:56:08 +00:00
await sleep ( 100 ) ;
}
2022-08-02 10:41:32 +00:00
console . log ( ` dsa: Found ' ${ nameOfAudioDevice } ' ` ) ;
2022-07-07 11:11:51 +00:00
return audioDevice ;
} ;
2022-11-22 15:35:47 +00:00
function setGetDisplayMedia ( video = true , overrideArgs = undefined ) {
2022-07-09 20:07:14 +00:00
const getDisplayMedia = async ( ... args ) => {
var id ;
try {
let myDiscordAudioSink = await getAudioDevice (
"discord-screenaudio-virtmic"
) ;
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 (
... ( overrideArgs
? [ overrideArgs ]
: args || [ { video : true , audio : true } ] )
2022-07-07 11:11:51 +00:00
) ;
2022-07-09 20:07:14 +00:00
gdm . addTrack ( track ) ;
2022-11-22 15:35:47 +00:00
if ( ! video ) for ( const track of gdm . getVideoTracks ( ) ) track . enabled = false ;
2022-07-09 20:07:14 +00:00
return gdm ;
} ;
navigator . mediaDevices . getDisplayMedia = getDisplayMedia ;
}
setGetDisplayMedia ( ) ;
const clonedElements = [ ] ;
const hiddenElements = [ ] ;
let wasStreamActive = false ;
2023-01-13 22:33:47 +00:00
function createButton ( text , onClick ) {
const button = document . createElement ( "button" ) ;
button . style . marginBottom = "20px" ;
button . classList =
"button-f2h6uQ lookFilled-yCfaCM colorBrand-I6CyqQ sizeSmall-wU2dO- grow-2sR_-F" ;
button . innerText = text ;
button . addEventListener ( "click" , onClick ) ;
return button ;
}
function createSwitch ( text , enabled , onClick ) {
const container = document . createElement ( "div" ) ;
container . style . marginBottom = "20px" ;
container . className = "labelRow-2jl9gK" ;
const label = document . createElement ( "label" ) ;
label . innerText = text ;
label . className = "title-2dsDLn" ;
container . appendChild ( label ) ;
const svg = document . createElement ( "div" ) ;
container . appendChild ( svg ) ;
function setSvgDisabled ( ) {
svg . innerHTML = ` <div class="container-2nx-BQ default-colors" style="opacity: 1; background-color: rgb(114, 118, 125);"><svg class="slider-32CRPX" viewBox="0 0 28 20" preserveAspectRatio="xMinYMid meet" aria-hidden="true" style="left: -3px;"><rect fill="white" x="4" y="0" height="20" width="20" rx="10"></rect><svg viewBox="0 0 20 20" fill="none"><path fill="rgba(114, 118, 125, 1)" d="M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z"></path><path fill="rgba(114, 118, 125, 1)" d="M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z"></path></svg></svg></div> ` ;
}
function setSvgEnabled ( ) {
svg . innerHTML = ` <div class="container-2nx-BQ default-colors checked-25WXMf" style="opacity: 1; background-color: rgb(59, 165, 92);"><svg class="slider-32CRPX" viewBox="0 0 28 20" preserveAspectRatio="xMinYMid meet" aria-hidden="true" style="left: 12px;"><rect fill="white" x="4" y="0" height="20" width="20" rx="10"></rect><svg viewBox="0 0 20 20" fill="none"><path fill="rgba(59, 165, 92, 1)" d="M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z"></path><path fill="rgba(59, 165, 92, 1)" d="M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z"></path></svg></svg></div> ` ;
}
function updateSvg ( ) {
if ( enabled ) setSvgEnabled ( ) ;
else setSvgDisabled ( ) ;
}
container . addEventListener ( "click" , ( ) => {
enabled = ! enabled ;
updateSvg ( ) ;
onClick ( enabled ) ;
} ) ;
updateSvg ( ) ;
return container ;
}
2022-07-09 20:07:14 +00:00
setInterval ( ( ) => {
const streamActive =
document . getElementsByClassName ( "panel-2ZFCRb activityPanel-9icbyU" )
. length > 0 ;
if ( ! streamActive && wasStreamActive )
console . log ( "!discord-screenaudio-stream-stopped" ) ;
wasStreamActive = streamActive ;
if ( streamActive ) {
clonedElements . forEach ( ( el ) => {
el . remove ( ) ;
} ) ;
clonedElements . length = 0 ;
hiddenElements . forEach ( ( el ) => {
el . style . display = "block" ;
} ) ;
hiddenElements . length = 0 ;
} else {
2022-07-28 13:09:06 +00:00
for ( const el of [
document . getElementsByClassName ( "actionButtons-2vEOUh" ) ? . [ 0 ] ? . children [ 1 ] ,
document . querySelector (
".wrapper-3t3Yqv > div > div > div > div > .controlButton-2PMNom"
) ,
] ) {
if ( ! el ) continue ;
if ( el . classList . contains ( "discord-screenaudio-cloned" ) ) continue ;
el . classList . add ( "discord-screenaudio-cloned" ) ;
2022-07-09 20:07:14 +00:00
elClone = el . cloneNode ( true ) ;
elClone . title = "Share Your Screen with Audio" ;
elClone . addEventListener ( "click" , ( ) => {
console . log ( "!discord-screenaudio-start-stream" ) ;
} ) ;
const initialDisplay = el . style . display ;
2022-11-22 15:35:47 +00:00
window . discordScreenaudioStartStream = (
video ,
width ,
height ,
frameRate
) => {
window . discordScreenaudioResolutionString = video
? ` ${ height } p ${ frameRate } FPS `
: "Audio Only" ;
setGetDisplayMedia ( video , {
2022-07-09 20:07:14 +00:00
audio : true ,
video : { width , height , frameRate } ,
} ) ;
el . click ( ) ;
el . style . display = initialDisplay ;
elClone . remove ( ) ;
} ;
el . style . display = "none" ;
el . parentNode . insertBefore ( elClone , el ) ;
clonedElements . push ( elClone ) ;
hiddenElements . push ( el ) ;
}
2022-07-07 11:11:51 +00:00
}
2022-07-09 20:07:14 +00:00
2022-07-14 12:43:52 +00:00
// Add about text in settings
2022-07-09 20:07:14 +00:00
if (
document . getElementsByClassName ( "dirscordScreenaudioAboutText" ) . length == 0
) {
for ( const el of document . getElementsByClassName ( "info-3pQQBb" ) ) {
2022-10-10 19:50:26 +00:00
let aboutEl ;
if ( window . discordScreenaudioKXMLGUI ) {
aboutEl = document . createElement ( "a" ) ;
aboutEl . addEventListener ( "click" , ( ) => {
console . log ( "!discord-screenaudio-about" ) ;
} ) ;
} else {
aboutEl = document . createElement ( "div" ) ;
}
2022-07-28 15:34:54 +00:00
aboutEl . innerText = ` discord-screenaudio ${ window . discordScreenaudioVersion } ` ;
2022-07-09 20:07:14 +00:00
aboutEl . style . fontSize = "12px" ;
aboutEl . style . color = "var(--text-muted)" ;
2022-07-28 15:34:54 +00:00
aboutEl . style . textTransform = "none" ;
2022-07-09 20:07:14 +00:00
aboutEl . classList . add ( "dirscordScreenaudioAboutText" ) ;
2022-10-10 19:50:26 +00:00
aboutEl . style . cursor = "pointer" ;
2022-07-09 20:07:14 +00:00
el . appendChild ( aboutEl ) ;
}
}
2022-07-14 12:43:52 +00:00
// Remove stream settings if stream is active
document . getElementById ( "manage-streams-change-windows" ) ? . remove ( ) ;
document . querySelector ( ` [aria-label="Stream Settings"] ` ) ? . remove ( ) ;
2022-09-21 15:32:41 +00:00
2022-10-10 19:50:26 +00:00
// Add event listener for keybind tab
if (
document
. getElementById ( "keybinds-tab" )
? . getElementsByClassName (
2023-01-09 21:20:11 +00:00
"container-3jbRo5 info-1hMolH browserNotice-1u-Y5o"
2022-10-10 19:50:26 +00:00
) . length
) {
const el = document
. getElementById ( "keybinds-tab" )
. getElementsByClassName ( "children-1xdcWE" ) [ 0 ] ;
const div = document . createElement ( "div" ) ;
div . style . marginBottom = "50px" ;
2023-01-13 22:33:47 +00:00
div . appendChild (
createButton ( "Edit Global Keybinds" , ( ) => {
console . log ( "!discord-screenaudio-keybinds" ) ;
} )
) ;
2022-10-10 19:50:26 +00:00
el . innerHTML = "" ;
el . appendChild ( div ) ;
}
2022-11-22 15:35:47 +00:00
const buttonContainer =
document . getElementsByClassName ( "container-YkUktl" ) [ 0 ] ;
2022-10-25 15:01:10 +00:00
if ( ! buttonContainer ) {
2022-11-22 15:35:47 +00:00
console . log (
"dsa: Cannot locate Mute/Deafen/Settings button container, please report this on GitHub"
) ;
2022-10-25 15:01:10 +00:00
}
2022-11-22 15:35:47 +00:00
const muteBtn = buttonContainer
? buttonContainer . getElementsByClassName (
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F"
) [ 0 ]
: null ;
2022-10-25 15:01:10 +00:00
window . discordScreenaudioToggleMute = ( ) => muteBtn && muteBtn . click ( ) ;
2022-11-22 15:35:47 +00:00
const deafenBtn = buttonContainer
? buttonContainer . getElementsByClassName (
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F"
) [ 1 ]
: null ;
2022-10-25 15:01:10 +00:00
window . discordScreenaudioToggleDeafen = ( ) => deafenBtn && deafenBtn . click ( ) ;
2022-10-10 19:50:26 +00:00
2022-09-21 15:32:41 +00:00
if ( window . discordScreenaudioResolutionString ) {
for ( const el of document . getElementsByClassName (
"qualityIndicator-39wQDy"
) ) {
el . innerHTML = window . discordScreenaudioResolutionString ;
}
}
2023-01-13 22:33:47 +00:00
const accountTab = document . getElementById ( "my-account-tab" ) ;
if ( accountTab ) {
const discordScreenaudioSettings = document . getElementById (
"discord-screenaudio-settings"
) ;
if ( ! discordScreenaudioSettings ) {
const firstDivider = accountTab . getElementsByClassName (
"divider-_0um2u marginTop40-Q4o1tS"
) [ 0 ] ;
if ( firstDivider ) {
const section = document . createElement ( "div" ) ;
section . className = "marginTop40-Q4o1tS" ;
section . id = "discord-screenaudio-settings" ;
const title = document . createElement ( "h2" ) ;
title . className =
"h1-34Txb0 title-3hptVQ defaultColor-2cKwKo defaultMarginh1-EURXsm" ;
title . innerText = "discord-screenaudio" ;
section . appendChild ( title ) ;
section . appendChild (
createButton ( "Edit Global Keybinds" , ( ) => {
console . log ( "!discord-screenaudio-keybinds" ) ;
} )
) ;
section . appendChild (
createSwitch (
"Move discord-screenaudio to the system tray instead of closing" ,
window . discordScreenaudioTrayEnabled ,
( enabled ) => {
console . log ( ` !discord-screenaudio-tray- ${ enabled } ` ) ;
}
)
) ;
const divider = document . createElement ( "div" ) ;
divider . className = "divider-_0um2u marginTop40-Q4o1tS" ;
firstDivider . after ( section ) ;
section . after ( divider ) ;
}
}
}
2022-07-26 13:48:01 +00:00
} , 500 ) ;
2022-07-27 13:02:51 +00:00
// Fix for broken discord notifications after restart
// (https://github.com/maltejur/discord-screenaudio/issues/17)
Notification . requestPermission ( ) ;