Skip to content

Commit

Permalink
Merge pull request #171 from TeaSpeak/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
WolverinDEV authored Feb 16, 2021
2 parents f75a6e2 + c4575b2 commit 477f4ee
Show file tree
Hide file tree
Showing 33 changed files with 744 additions and 259 deletions.
9 changes: 9 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# Changelog:
* **15.02.21**
- Fixed critical bug within the event registry class
- Added a dropdown for the microphone control button to quickly change microphones
- Fixed the microphone settings microphone selection (The default device wasn't selected)
- Adding a hint whatever the device is the default device or not
- Fixed issue [#169](https://github.com/TeaSpeak/TeaWeb/issues/169) (Adding permissions dosn't work for TS3 server)
- Fixed issue [#166](https://github.com/TeaSpeak/TeaWeb/issues/166) (Private conversations are not accessible when IndexDB could not be opened)
- Using the last used emoji to indicate the chat emoji button

* **22.01.21**
- Allowing the user to easily change the channel name mode
- Fixed channel name mode parsing
Expand Down
1 change: 1 addition & 0 deletions shared/js/ConnectionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
name: "server manager init",
function: async () => {
server_connections = new ConnectionManager();
(window as any).server_connections = server_connections;
},
priority: 80
});
2 changes: 2 additions & 0 deletions shared/js/connection/ConnectionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export abstract class AbstractServerConnection {
abstract connected() : boolean;
abstract disconnect(reason?: string) : Promise<void>;

abstract getServerType() : "teaspeak" | "teamspeak" | "unknown";

abstract getVoiceConnection() : AbstractVoiceConnection;
abstract getVideoConnection() : VideoConnection;

Expand Down
36 changes: 18 additions & 18 deletions shared/js/connection/rtc/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {ErrorCode} from "tc-shared/connection/ErrorCode";
import {WhisperTarget} from "tc-shared/voice/VoiceWhisper";
import {globalAudioContext} from "tc-backend/audio/player";
import {VideoBroadcastConfig, VideoBroadcastType} from "tc-shared/connection/VideoConnection";
import {Settings, settings} from "tc-shared/settings";

const kSdpCompressionMode = 1;

Expand Down Expand Up @@ -372,9 +373,7 @@ class InternalRemoteRTPAudioTrack extends RemoteRTPAudioTrack {
if(state === 1) {
validateInfo();
this.shouldReplay = true;
if(this.gainNode) {
this.gainNode.gain.value = this.gain;
}
this.updateGainNode();
this.setState(RemoteRTPTrackState.Started);
} else {
/* There wil be no info present */
Expand All @@ -383,9 +382,7 @@ class InternalRemoteRTPAudioTrack extends RemoteRTPAudioTrack {
/* since we're might still having some jitter stuff */
this.muteTimeout = setTimeout(() => {
this.shouldReplay = false;
if(this.gainNode) {
this.gainNode.gain.value = 0;
}
this.updateGainNode();
}, 1000);
}
}
Expand Down Expand Up @@ -882,29 +879,32 @@ export class RTCConnection {
iceServers: [{ urls: ["stun:stun.l.google.com:19302", "stun:stun1.l.google.com:19302"] }]
});

/* If set to false FF failed: FIXME! */
const kAddGenericTransceiver = true;

if(this.audioSupport) {
this.currentTransceiver["audio"] = this.peer.addTransceiver("audio");
this.currentTransceiver["audio-whisper"] = this.peer.addTransceiver("audio");

/* add some other transceivers for later use */
for(let i = 0; i < 8 && kAddGenericTransceiver; i++) {
const transceiver = this.peer.addTransceiver("audio");
/* we only want to received on that and don't share any bandwidth limits */
transceiver.direction = "recvonly";
if(window.detectedBrowser.name === "firefox") {
/*
* For some reason FF (<= 85.0) does not replay any audio from extra added transceivers.
* On the other hand, if the server is creating that track or we're using it for sending audio as well
* it works. So we just wait for the server to come up with new streams (even though we need to renegotiate...).
* For Chrome we only need to negotiate once in most cases.
* Side note: This does not apply to video channels!
*/
} else {
/* add some other transceivers for later use */
for(let i = 0; i < settings.getValue(Settings.KEY_RTC_EXTRA_AUDIO_CHANNELS); i++) {
this.peer.addTransceiver("audio", { direction: "recvonly" });
}
}
}

this.currentTransceiver["video"] = this.peer.addTransceiver("video");
this.currentTransceiver["video-screen"] = this.peer.addTransceiver("video");

/* add some other transceivers for later use */
for(let i = 0; i < 4 && kAddGenericTransceiver; i++) {
const transceiver = this.peer.addTransceiver("video");
/* we only want to received on that and don't share any bandwidth limits */
transceiver.direction = "recvonly";
for(let i = 0; i < settings.getValue(Settings.KEY_RTC_EXTRA_VIDEO_CHANNELS); i++) {
this.peer.addTransceiver("video", { direction: "recvonly" });
}

this.peer.onicecandidate = event => this.handleLocalIceCandidate(event.candidate);
Expand Down
36 changes: 27 additions & 9 deletions shared/js/connection/rtc/RemoteTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class RemoteRTPTrack {
}

getSsrc() : number {
return this.ssrc;
return this.ssrc >>> 0;
}

getTrack() : MediaStreamTrack {
Expand Down Expand Up @@ -144,7 +144,20 @@ export class RemoteRTPAudioTrack extends RemoteRTPTrack {
this.htmlAudioNode.msRealTime = true;

/*
TODO: ontimeupdate may gives us a hint whatever we're still replaying audio or not
{
const track = transceiver.receiver.track;
for(let key in track) {
if(!key.startsWith("on")) {
continue;
}
track[key] = () => console.log("Track %d: %s", this.getSsrc(), key);
}
}
*/

/*
//TODO: ontimeupdate may gives us a hint whatever we're still replaying audio or not
for(let key in this.htmlAudioNode) {
if(!key.startsWith("on")) {
continue;
Expand All @@ -153,7 +166,7 @@ export class RemoteRTPAudioTrack extends RemoteRTPTrack {
this.htmlAudioNode[key] = () => console.log("AudioElement %d: %s", this.getSsrc(), key);
this.htmlAudioNode.ontimeupdate = () => {
console.log("AudioElement %d: Time update. Current time: %d", this.getSsrc(), this.htmlAudioNode.currentTime, this.htmlAudioNode.buffered)
}
};
}
*/

Expand All @@ -166,8 +179,7 @@ export class RemoteRTPAudioTrack extends RemoteRTPTrack {
const audioContext = globalAudioContext();
this.audioNode = audioContext.createMediaStreamSource(this.mediaStream);
this.gainNode = audioContext.createGain();

this.gainNode.gain.value = this.shouldReplay ? this.gain : 0;
this.updateGainNode();

this.audioNode.connect(this.gainNode);
this.gainNode.connect(audioContext.destination);
Expand Down Expand Up @@ -195,10 +207,7 @@ export class RemoteRTPAudioTrack extends RemoteRTPTrack {

setGain(value: number) {
this.gain = value;

if(this.gainNode) {
this.gainNode.gain.value = this.shouldReplay ? this.gain : 0;
}
this.updateGainNode();
}

/**
Expand All @@ -209,4 +218,13 @@ export class RemoteRTPAudioTrack extends RemoteRTPTrack {
this.gainNode.gain.value = 0;
}
}

protected updateGainNode() {
if(!this.gainNode) {
return;
}

this.gainNode.gain.value = this.shouldReplay ? this.gain : 0;
//console.error("Change gain for %d to %f (%o)", this.getSsrc(), this.gainNode.gain.value, this.shouldReplay);
}
}
4 changes: 2 additions & 2 deletions shared/js/connection/rtc/SdpUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class SdpProcessor {
rate: 48000,
encoding: 2,
fmtp: { minptime: 1, maxptime: 20, useinbandfec: 1, usedtx: 1, stereo: 0, "sprop-stereo": 0 },
rtcpFb: [ "transport-cc" ]
rtcpFb: [ "transport-cc", "nack", "goog-remb" ]
},
{
// Opus Stereo/Opus Music
Expand All @@ -37,7 +37,7 @@ export class SdpProcessor {
rate: 48000,
encoding: 2,
fmtp: { minptime: 1, maxptime: 20, useinbandfec: 1, usedtx: 1, stereo: 1, "sprop-stereo": 1 },
rtcpFb: [ "transport-cc" ]
rtcpFb: [ "transport-cc", "nack", "goog-remb" ]
},
];

Expand Down
27 changes: 19 additions & 8 deletions shared/js/conversations/PrivateConversationHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,17 @@ async function requestDatabase() {
} else if(databaseMode === "opening" || databaseMode === "updating") {
await new Promise(resolve => databaseStateChangedCallbacks.push(resolve));
} else if(databaseMode === "closed") {
await doOpenDatabase(false);
try {
await doOpenDatabase(false);
} catch (error) {
currentDatabase = undefined;
if(databaseMode !== "closed") {
databaseMode = "closed";
fireDatabaseStateChanged();
}

throw error;
}
}
}
}
Expand Down Expand Up @@ -143,6 +153,11 @@ async function importChatsFromCacheStorage(database: IDBDatabase) {
}

async function doOpenDatabase(forceUpgrade: boolean) {
if(!('indexedDB' in window)) {
loader.critical_error(tr("Missing Indexed DB support"));
throw tr("Missing Indexed DB support");
}

if(databaseMode === "closed") {
databaseMode = "opening";
fireDatabaseStateChanged();
Expand Down Expand Up @@ -231,13 +246,8 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
priority: 0,
name: "Chat history setup",
function: async () => {
if(!('indexedDB' in window)) {
loader.critical_error(tr("Missing Indexed DB support"));
throw tr("Missing Indexed DB support");
}

try {
await doOpenDatabase(false);
await requestDatabase();
logDebug(LogCategory.CHAT, tr("Successfully initialized private conversation history database"));
} catch (error) {
logError(LogCategory.CHAT, tr("Failed to initialize private conversation history database: %o"), error);
Expand All @@ -255,8 +265,9 @@ export async function queryConversationEvents(clientUniqueId: string, query: {
const storeName = clientUniqueId2StoreName(clientUniqueId);

await requestDatabase();
if(!currentDatabase.objectStoreNames.contains(storeName))
if(!currentDatabase.objectStoreNames.contains(storeName)) {
return { events: [], hasMore: false };
}

const transaction = currentDatabase.transaction(storeName, "readonly");
const store = transaction.objectStore(storeName);
Expand Down
14 changes: 14 additions & 0 deletions shared/js/conversations/PrivateConversationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,20 @@ export class PrivateConversation extends AbstractChat<PrivateConversationEvents>
this.presentMessages = result.events.filter(e => e.type === "message");
this.setHistory(!!result.hasMore);

this.setCurrentMode("normal");
}).catch(error => {
console.error("Error open!");
this.presentEvents = [];
this.presentMessages = [];
this.setHistory(false);

this.registerChatEvent({
type: "query-failed",
timestamp: Date.now(),
uniqueId: "la-" + this.chatId + "-" + Date.now(),
message: tr("Failed to query chat history:\n") + error
}, false);

this.setCurrentMode("normal");
});
}
Expand Down
3 changes: 2 additions & 1 deletion shared/js/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ export class Registry<Events extends EventMap<Events> = EventMap<any>> implement
}
}

for(const handler of this.persistentEventHandler[event.type] || []) {
const handlers = [...(this.persistentEventHandler[event.type] || [])];
for(const handler of handlers) {
handler(event);
}

Expand Down
29 changes: 16 additions & 13 deletions shared/js/file/FileManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,9 @@ export class FileManager {
"proto": 1
}, {process_result: false});

if(transfer.transferState() === FileTransferState.INITIALIZING)
if(transfer.transferState() === FileTransferState.INITIALIZING) {
throw tr("missing transfer start notify");
}

} catch (error) {
transfer.setFailed({
Expand Down Expand Up @@ -620,8 +621,9 @@ export class FileManager {
transfer: transfer,
executeCallback: async () => {
await callbackInitialize(transfer); /* noexcept */
if(transfer.transferState() !== FileTransferState.CONNECTING)
if(transfer.transferState() !== FileTransferState.CONNECTING) {
return;
}

try {
const provider = TransferProvider.provider();
Expand All @@ -633,12 +635,13 @@ export class FileManager {
return;
}

if(transfer instanceof FileDownloadTransfer)
if(transfer instanceof FileDownloadTransfer) {
provider.executeFileDownload(transfer);
else if(transfer instanceof FileUploadTransfer)
} else if(transfer instanceof FileUploadTransfer) {
provider.executeFileUpload(transfer);
else
} else {
throw tr("unknown transfer type");
}
} catch (error) {
const message = typeof error === "string" ? error : error instanceof Error ? error.message : tr("Unknown error");
transfer.setFailed({
Expand All @@ -651,7 +654,7 @@ export class FileManager {
finishPromise: new Promise(resolve => {
const unregisterTransfer = () => {
transfer.events.off("notify_state_updated", stateListener);
transfer.events.off("action_request_cancel", cancelListener);
transfer.events.off("notify_transfer_canceled", unregisterTransfer);

const index = this.registeredTransfers_.findIndex(e => e.transfer === transfer);
if(index === -1) {
Expand Down Expand Up @@ -681,6 +684,9 @@ export class FileManager {
} else {
logWarn(LogCategory.FILE_TRANSFER, tra("File transfer finished callback called with invalid transfer state ({0})", FileTransferState[state]));
}

/* destroy the transfer after all events have been fired */
setTimeout(() => transfer.destroy(), 250);
};

const stateListener = () => {
Expand All @@ -690,13 +696,9 @@ export class FileManager {
}
};

const cancelListener = () => {
unregisterTransfer();
transfer.events.fire_later("notify_transfer_canceled", {}, resolve);
};

transfer.events.on("notify_state_updated", stateListener);
transfer.events.on("action_request_cancel", cancelListener);
transfer.events.on("notify_transfer_canceled", unregisterTransfer);
stateListener();
})
});

Expand All @@ -705,8 +707,9 @@ export class FileManager {
}

private scheduleTransferUpdate() {
if(this.scheduledTransferUpdate)
if(this.scheduledTransferUpdate) {
return;
}

this.scheduledTransferUpdate = setTimeout(() => {
this.scheduledTransferUpdate = undefined;
Expand Down
Loading

0 comments on commit 477f4ee

Please sign in to comment.