No VoIP of any kind: neither 1:1 m.call.invite/answer/candidates nor group calls via MatrixRTC (MSC3401 / Element Call). Zero hits across the backend.
Discord voice is fully built in this project (discord_voice.rs, Songbird), so the audio plumbing and the call UI — CallView, IncomingCallPanel, device selection, level meters — already exist and are protocol-agnostic in the frontend.
Done looks like: 1:1 m.call.* first, reusing the existing call UI. Group calls are a much larger piece.
No VoIP of any kind: neither 1:1 `m.call.invite`/`answer`/`candidates` nor group calls via MatrixRTC (MSC3401 / Element Call). Zero hits across the backend.
Discord voice is fully built in this project (`discord_voice.rs`, Songbird), so the audio plumbing and the call UI — `CallView`, `IncomingCallPanel`, device selection, level meters — already exist and are protocol-agnostic in the frontend.
**Done looks like:** 1:1 `m.call.*` first, reusing the existing call UI. Group calls are a much larger piece.
Assessed while working through the Matrix issues, and not started — the blocker is structural rather than a matter of effort, so it is worth writing down before anybody picks this up.
The existing voice stack cannot be reused. moho's voice is Songbird, which speaks Discord's own voice protocol: its own UDP handshake, its own encryption, Opus over a Discord voice gateway. Matrix calls are WebRTC — ICE, DTLS-SRTP, SDP negotiation, TURN credentials fetched from the homeserver. The two share the fact that audio is Opus and nothing else. So this is not "wire Matrix into the call code"; it is adding a second, larger media stack (webrtc-rs or equivalent) to the daemon.
What is already reusable is the half above the media: CallView, IncomingCallPanel, the ringtone, device selection and the level meters are protocol-agnostic in the frontend, and getIncomingCalls/acceptCall/declineCall are generic RPCs that Discord happens to be the only implementor of. So the client work is small and the daemon work is large.
Rough shape if it is wanted: 1:1 m.call.invite/m.call.answer/m.call.candidates/m.call.hangup over to-device or room events, a WebRTC peer connection per call, and TURN credentials from /_matrix/client/v3/voip/turnServer. Group calls via MatrixRTC/Element Call (MSC3401) are a considerably larger thing again and should not be attempted in the same pass.
Worth weighing against #14 (Discord screen share), which is blocked on the same absence for a different reason — Songbird carries audio only. A WebRTC stack in the daemon would not fix#14 by itself, but the two are the only reasons anybody would add one, so they are worth deciding together.
Assessed while working through the Matrix issues, and not started — the blocker is structural rather than a matter of effort, so it is worth writing down before anybody picks this up.
**The existing voice stack cannot be reused.** moho's voice is Songbird, which speaks Discord's own voice protocol: its own UDP handshake, its own encryption, Opus over a Discord voice gateway. Matrix calls are **WebRTC** — ICE, DTLS-SRTP, SDP negotiation, TURN credentials fetched from the homeserver. The two share the fact that audio is Opus and nothing else. So this is not "wire Matrix into the call code"; it is adding a second, larger media stack (`webrtc-rs` or equivalent) to the daemon.
**What is already reusable** is the half above the media: `CallView`, `IncomingCallPanel`, the ringtone, device selection and the level meters are protocol-agnostic in the frontend, and `getIncomingCalls`/`acceptCall`/`declineCall` are generic RPCs that Discord happens to be the only implementor of. So the client work is small and the daemon work is large.
**Rough shape if it is wanted:** 1:1 `m.call.invite`/`m.call.answer`/`m.call.candidates`/`m.call.hangup` over to-device or room events, a WebRTC peer connection per call, and TURN credentials from `/_matrix/client/v3/voip/turnServer`. Group calls via MatrixRTC/Element Call (MSC3401) are a considerably larger thing again and should not be attempted in the same pass.
Worth weighing against #14 (Discord screen share), which is blocked on the same absence for a different reason — Songbird carries audio only. A WebRTC stack in the daemon would not fix #14 by itself, but the two are the only reasons anybody would add one, so they are worth deciding together.
1:1 m.call.* calls, voice and video, with the media in the window (Chromium has a complete WebRTC stack; the daemon would have to grow a browser) and the signalling in the daemon (an offer, an answer, the network paths and a hangup are room events, encrypted where the room is). TURN credentials come from the homeserver's own /voip/turnServer. Screen sharing is included, as its own track added to a call in progress.
Verified live between two homeservers: a call placed from matrix.salastil.com rang on poa.st, was answered, and both ends reported connected with a live audio track each way — then a shared screen arrived at the far end as a second track and was drawn.
Three things this turned up on the way: Chromium will not hand over a microphone unasked and an unanswered permission request hangs rather than failing (which is what a call that never started looked like); the daemon's existing send_room_event always sends m.room.message, so a call event routed through it went out with its type in the room-id slot; and a machine with no camera now drops the camera and says so rather than failing the whole request, microphone included.
Group calls (MatrixRTC / MSC3401) are not included — as the issue says, a much larger piece.
Finished — https://git.salastil.com/Salastil/nobilis/commit/c9d06bc and https://git.salastil.com/Salastil/moho/commit/5d99b42
1:1 `m.call.*` calls, voice and video, with the media in the window (Chromium has a complete WebRTC stack; the daemon would have to grow a browser) and the signalling in the daemon (an offer, an answer, the network paths and a hangup are room events, encrypted where the room is). TURN credentials come from the homeserver's own `/voip/turnServer`. Screen sharing is included, as its own track added to a call in progress.
**Verified live between two homeservers:** a call placed from matrix.salastil.com rang on poa.st, was answered, and both ends reported connected with a live audio track each way — then a shared screen arrived at the far end as a second track and was drawn.
Three things this turned up on the way: Chromium will not hand over a microphone unasked and an unanswered permission request *hangs* rather than failing (which is what a call that never started looked like); the daemon's existing `send_room_event` always sends `m.room.message`, so a call event routed through it went out with its type in the room-id slot; and a machine with no camera now drops the camera and says so rather than failing the whole request, microphone included.
Group calls (MatrixRTC / MSC3401) are not included — as the issue says, a much larger piece.
The multi-party view on top of the 1:1 call above: a fitted tile grid, a green ring on whoever is talking, click-to-enlarge with the others in a strip underneath, and a corner view that names who is in the call.
Finished — https://git.salastil.com/Salastil/moho/commit/7eec5bf
The multi-party view on top of the 1:1 call above: a fitted tile grid, a green ring on whoever is talking, click-to-enlarge with the others in a strip underneath, and a corner view that names who is in the call.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
No VoIP of any kind: neither 1:1
m.call.invite/answer/candidatesnor group calls via MatrixRTC (MSC3401 / Element Call). Zero hits across the backend.Discord voice is fully built in this project (
discord_voice.rs, Songbird), so the audio plumbing and the call UI —CallView,IncomingCallPanel, device selection, level meters — already exist and are protocol-agnostic in the frontend.Done looks like: 1:1
m.call.*first, reusing the existing call UI. Group calls are a much larger piece.Assessed while working through the Matrix issues, and not started — the blocker is structural rather than a matter of effort, so it is worth writing down before anybody picks this up.
The existing voice stack cannot be reused. moho's voice is Songbird, which speaks Discord's own voice protocol: its own UDP handshake, its own encryption, Opus over a Discord voice gateway. Matrix calls are WebRTC — ICE, DTLS-SRTP, SDP negotiation, TURN credentials fetched from the homeserver. The two share the fact that audio is Opus and nothing else. So this is not "wire Matrix into the call code"; it is adding a second, larger media stack (
webrtc-rsor equivalent) to the daemon.What is already reusable is the half above the media:
CallView,IncomingCallPanel, the ringtone, device selection and the level meters are protocol-agnostic in the frontend, andgetIncomingCalls/acceptCall/declineCallare generic RPCs that Discord happens to be the only implementor of. So the client work is small and the daemon work is large.Rough shape if it is wanted: 1:1
m.call.invite/m.call.answer/m.call.candidates/m.call.hangupover to-device or room events, a WebRTC peer connection per call, and TURN credentials from/_matrix/client/v3/voip/turnServer. Group calls via MatrixRTC/Element Call (MSC3401) are a considerably larger thing again and should not be attempted in the same pass.Worth weighing against #14 (Discord screen share), which is blocked on the same absence for a different reason — Songbird carries audio only. A WebRTC stack in the daemon would not fix #14 by itself, but the two are the only reasons anybody would add one, so they are worth deciding together.
Finished — https://git.salastil.com/Salastil/nobilis/commit/c9d06bc and https://git.salastil.com/Salastil/moho/commit/5d99b42
1:1
m.call.*calls, voice and video, with the media in the window (Chromium has a complete WebRTC stack; the daemon would have to grow a browser) and the signalling in the daemon (an offer, an answer, the network paths and a hangup are room events, encrypted where the room is). TURN credentials come from the homeserver's own/voip/turnServer. Screen sharing is included, as its own track added to a call in progress.Verified live between two homeservers: a call placed from matrix.salastil.com rang on poa.st, was answered, and both ends reported connected with a live audio track each way — then a shared screen arrived at the far end as a second track and was drawn.
Three things this turned up on the way: Chromium will not hand over a microphone unasked and an unanswered permission request hangs rather than failing (which is what a call that never started looked like); the daemon's existing
send_room_eventalways sendsm.room.message, so a call event routed through it went out with its type in the room-id slot; and a machine with no camera now drops the camera and says so rather than failing the whole request, microphone included.Group calls (MatrixRTC / MSC3401) are not included — as the issue says, a much larger piece.
Finished — https://git.salastil.com/Salastil/moho/commit/7eec5bf
The multi-party view on top of the 1:1 call above: a fitted tile grid, a green ring on whoever is talking, click-to-enlarge with the others in a strip underneath, and a corner view that names who is in the call.