diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index 6400fa3..64f35f3 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -796,7 +796,7 @@ class Channel extends SnowFlake { } if (this.pinnedMessages.length === 0) { const b = document.createElement("b"); - b.classList.add('noPins'); + b.classList.add("noPins"); b.textContent = I18n.noPins(); div.append(b); return; diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index a60683a..689c688 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -1095,9 +1095,7 @@ class Localuser { async joinVoice(channel: Channel) { if (!this.voiceFactory) return; if (!this.ws) return; - this.ws.send( - JSON.stringify(this.voiceFactory.joinVoice(channel.id, channel.guild.id, this.mute)), - ); + this.voiceFactory.joinVoice(channel.id, channel.guild.id, this.mute); return undefined; } regenVoiceIcons = () => {}; diff --git a/src/webpage/voice.ts b/src/webpage/voice.ts index 0c293db..c19059b 100644 --- a/src/webpage/voice.ts +++ b/src/webpage/voice.ts @@ -8,6 +8,9 @@ import { webRTCSocket, } from "./jsontypes.js"; function forceVideo(video: HTMLVideoElement) { + video.controls = false; + //TODO loading? + video.poster; video.addEventListener("pause", () => { video.play(); }); @@ -57,45 +60,48 @@ class VoiceFactory { set mute(s) { const changed = this.imute !== s; this.imute = s; + this.sendVoiceStateIfNeeded(); if (this.currentVoice && changed) { this.currentVoice.updateMute(); - this.updateSelf(); } } disconect() { if (!this.curChan) return; this.curChan = null; this.curGuild = null; - this.handleGateway({ + this.sendVoiceState(); + } + + updateSelf() { + if (this.currentVoice && this.currentVoice.open) { + this.sendVoiceState(); + } + } + curGuild: string | null = null; + curChan: string | null = null; + lastSentState = ""; + sendVoiceStateIfNeeded() { + const state = this.calcState; + if (JSON.stringify(state) !== this.lastSentState) this.sendVoiceState(); + } + get calcState() { + return { op: 4, d: { guild_id: this.curGuild, channel_id: this.curChan, self_mute: this.imute, self_deaf: false, - self_video: false, + self_video: (this.curGuild ?? false) && this.video, flags: 3, }, - }); + } as const; } - - updateSelf() { - if (this.currentVoice && this.currentVoice.open) { - this.handleGateway({ - op: 4, - d: { - guild_id: this.curGuild, - channel_id: this.curChan, - self_mute: this.imute, - self_deaf: false, - self_video: this.video, - flags: 3, - }, - }); - } + sendVoiceState() { + const send = this.calcState; + this.lastSentState = JSON.stringify(send); + this.handleGateway(send); } - curGuild: string | null = null; - curChan: string | null = null; joinVoice(channelId: string, guildId: string, self_mute = false) { const voice = this.voiceChannels.get(channelId); this.mute = self_mute; @@ -108,17 +114,7 @@ class VoiceFactory { voice.join(); this.currentVoice = voice; this.onJoin(voice); - return { - d: { - guild_id: guildId, - channel_id: channelId, - self_mute, - self_deaf: false, //todo - self_video: false, - flags: 2, //????? - }, - op: 4, - }; + this.sendVoiceState(); } leaveLive() { const userid = this.settings.id; @@ -745,14 +741,16 @@ a=rtcp-mux\r`; } return {video_ssrc, rtx_ssrc}; } - async makeOp12( - sender: RTCRtpSender | undefined | [RTCRtpSender, number] = this.ssrcMap.entries().next().value, - ) { + async makeOp12(sender: RTCRtpSender | undefined | [RTCRtpSender, number] = this.mic?.sender) { + //debugger; + //await new Promise((res) => setTimeout(res, 500)); + this.owner.sendVoiceStateIfNeeded(); console.warn("making 12?"); if (!this.ws) return; if (sender instanceof Array) { sender = sender[0]; } + //console.trace(sender === this.mic?.sender); let max_framerate = 20; let width = 1280; @@ -766,12 +764,40 @@ a=rtcp-mux\r`; console.log(this.ssrcMap); try { console.error("start 12"); + if (!video_ssrc) + this.ws.send( + JSON.stringify({ + op: 12, + d: { + audio_ssrc: 0, + video_ssrc: 0, + rtx_ssrc: 0, + streams: [ + { + type: "video", + rid: "100", + ssrc: video_ssrc, + active: !!video_ssrc, + quality: 100, + rtx_ssrc: rtx_ssrc, + max_bitrate: 2500000, //TODO + max_framerate, //TODO + max_resolution: {type: "fixed", width, height}, + }, + ], + }, + }), + ); this.ws.send( JSON.stringify({ op: 12, d: { audio_ssrc: - sender?.track?.kind === "audio" ? this.ssrcMap.get(sender as RTCRtpSender) : 0, + sender?.track?.kind === "audio" + ? this.owner.mute + ? 0 + : this.ssrcMap.get(sender as RTCRtpSender) + : 0, video_ssrc, rtx_ssrc, streams: [ @@ -884,8 +910,10 @@ a=rtcp-mux\r`; updateMute() { if (!this.micTrack) return; this.micTrack.enabled = !this.owner.mute; + //this.pc?.setLocalDescription(); + this.makeOp12(); } - mic?: RTCRtpSender; + mic?: RTCRtpTransceiver; micTrack?: MediaStreamTrack; onVideo = (_video: HTMLVideoElement, _id: string) => {}; videos = new Map(); @@ -978,10 +1006,9 @@ a=rtcp-mux\r`; console.warn("replaced track", cam); this.pc?.setLocalDescription((await this.pc?.createOffer()) || {}); + this.owner.updateSelf(); if (this.settings.stream) { this.makeOp12(); - } else { - this.owner.updateSelf(); } } onconnect = () => {}; @@ -1016,8 +1043,15 @@ a=rtcp-mux\r`; console.log(video); video.autoplay = true; + const settings = e.track.getConstraints(); - console.log("gotVideo?", media); + console.log("gotVideo?", media, settings); + settings.height = 300; + settings.width = 300; + e.track.applyConstraints(settings); + //e.track + + //if ("resizeMode" in settings) return; } @@ -1040,12 +1074,12 @@ a=rtcp-mux\r`; const audioStream = await navigator.mediaDevices.getUserMedia({video: false, audio: true}); const [track] = audioStream.getAudioTracks(); this.setupMic(audioStream); - const sender = pc.addTrack(track); + const sender = pc.addTransceiver(track); this.mic = sender; this.micTrack = track; track.enabled = !this.owner.mute; - this.senders.add(sender); + this.senders.add(sender.sender); console.log(sender); } else { pc.addTransceiver("audio", { @@ -1078,7 +1112,6 @@ a=rtcp-mux\r`; ], }); await this.startVideo(this.settings.live); - this.makeOp12(); } else { for (let i = 0; i < count; i++) { pc.addTransceiver("video", { @@ -1088,8 +1121,10 @@ a=rtcp-mux\r`; }); } } + //this.makeOp12(); this.pc = pc; + await this.makeOp12(this.mic?.sender); this.negotationneeded(); await new Promise((res) => setTimeout(res, 100)); let sdp = this.offer;