diff --git a/CHANGELOG b/CHANGELOG index 7d2b7e4..c755a5f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +0.1.2: +- Add channel support +- Notify user when browser does not support WebRTC + 0.1.1: - Fix static asset embedding issue diff --git a/pkg/web/channel.go b/pkg/web/channel.go index 6514092..79f843c 100644 --- a/pkg/web/channel.go +++ b/pkg/web/channel.go @@ -1,14 +1,39 @@ package web +import ( + "sync" +) + +type ChannelType int + +const ( + ChannelUnknown ChannelType = 0 + ChannelAll ChannelType = 1 + ChannelText ChannelType = 2 + ChannelVoice ChannelType = 3 +) + type Channel struct { ID int + Type ChannelType Name string Topic string Clients map[int]*Client + + *sync.Mutex } -func NewChannel(id int, name string, topic string) *Channel { - c := Channel{ID: id, Name: name, Topic: topic, Clients: make(map[int]*Client)} +func NewChannel(id int, t ChannelType) *Channel { + c := Channel{ID: id, Type: t, Clients: make(map[int]*Client), Mutex: new(sync.Mutex)} return &c } + +type ChannelListing struct { + ID int + Type ChannelType + Name string + Topic string +} + +type ChannelList map[int]*ChannelListing diff --git a/pkg/web/client.go b/pkg/web/client.go index f48c11e..86d7c34 100644 --- a/pkg/web/client.go +++ b/pkg/web/client.go @@ -29,7 +29,8 @@ type Client struct { AudioTracks map[int]*webrtc.Track VoiceIn chan []int16 - VoiceInLastActive time.Time + VoiceInActive time.Time + VoiceInNotify time.Time VoiceInTransmitting bool VoiceInLock *sync.Mutex @@ -38,6 +39,8 @@ type Client struct { VoiceOutActive []time.Time VoiceOutLock *sync.Mutex + Channel *Channel + Terminated chan bool } diff --git a/pkg/web/message.go b/pkg/web/message.go index 1d7c695..e1b6be4 100644 --- a/pkg/web/message.go +++ b/pkg/web/message.go @@ -22,7 +22,9 @@ const ( MessageTypingStop MessageType = 122 MessageTransmitStart MessageType = 123 MessageTransmitStop MessageType = 124 - MessageUsers MessageType = 130 + MessageServers MessageType = 130 + MessageChannels MessageType = 131 + MessageUsers MessageType = 132 ) func (t MessageType) String() string { @@ -57,3 +59,12 @@ func (t MessageType) String() string { return fmt.Sprintf("%d?", t) } } + +type Message struct { + S int // Source + N string // Source nickname + PC int // PeerConn + C int // Channel + T MessageType // Type + M []byte // Message +} diff --git a/pkg/web/public/assets/js/harmony.js b/pkg/web/public/assets/js/harmony.js index a3d7430..07e4f98 100644 --- a/pkg/web/public/assets/js/harmony.js +++ b/pkg/web/public/assets/js/harmony.js @@ -38,8 +38,13 @@ var muteOnMouseUp = true; var lastPing = 0; var userPing = 0; +var allChannels; +var voiceChannel = 0; +var disableVoice = false; +var voiceCompatibilityNotice = "Sorry, your browser does not support WebRTC. This is required join voice channels. Firefox (recommended) and Chrome support WebRTC."; + +var channelList = ''; var userList = ''; -var userListVoice = ''; var userListStatus = 'Loading...'; var MessageBinary = 2; @@ -59,7 +64,14 @@ var MessageTypingStart = 121; var MessageTypingStop = 122; var MessageTransmitStart = 123; var MessageTransmitStop = 124; -var MessageUsers = 130; +var MessageServers = 130; +var MessageChannels = 131; +var MessageUsers = 132; + +var ChannelUnknown = 0; +var ChannelAll = 1; +var ChannelText = 2; +var ChannelVoice = 3; var tagsToReplace = { '&': '&', @@ -98,34 +110,13 @@ function HandleInput(e) { } $(document).ready(function () { - $("#togglevoice").on("click touchstart", function () { - $("#chatinput").focus(); + // Confirm voice chat support + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia || !window.RTCPeerConnection) { + alert(voiceCompatibilityNotice); + Log(voiceCompatibilityNotice); - if (peerConnections.length > 0 || voice) { - // Quit voice chat - - voice = false; - - w(MessageQuit, ""); - - peerConnections.forEach(function (pc) { - pc.close(); - }); - peerConnections = []; - - $('#voicepttcontainer').css('display', 'none'); - - updateStatus(); - return; - } - - // Join voice chat - - var i; - for (i = 0; i < numConnections; i++) { - peerConnections.push(createPeerConnection(i)); - } - }); + disableVoice = true; + } $("#voiceptt").on("touchstart", function (e) { muteOnMouseUp = false; @@ -214,17 +205,16 @@ function createPeerConnection(id) { el.autoplay = true; el.srcObject = event.streams[0]; - voice = true; + if (id == 0) { + if (!shownPTTHelp) { + shownPTTHelp = true; - if (id == 0 && !shownPTTHelp) { - shownPTTHelp = true; + Log("Note: Push-to-talk is bound to <F8>"); + } - Log("Note: Push-to-talk is bound to <F8>"); + $('#voicepttcontainer').css('display', 'block'); + updateStatus(); } - - $('#voicepttcontainer').css('display', 'block'); - - updateStatus(); }; if (id == 0) { @@ -279,7 +269,6 @@ function onRTCDescription(id) { function Connect() { reconnectTimeout = null; if (webSocketReady() || ReconnectDelay === -1) { - alert('exit'); return; } @@ -351,17 +340,17 @@ function Connect() { Log(escapeEntities(p.N) + " connected"); } else if (p.T == MessageJoin) { - if (p.N === undefined) { + if (p.C === undefined || p.N === undefined) { return; } - Log(escapeEntities(p.N) + " joined &lobby"); + Log(escapeEntities(p.N) + " joined " + allChannels[p.C].Name); } else if (p.T == MessageQuit) { - if (p.N === undefined) { + if (p.C === undefined || p.N === undefined) { return; } - Log(escapeEntities(p.N) + " quit &lobby"); + Log(escapeEntities(p.N) + " quit " + allChannels[p.C].Name); } else if (p.T == MessageDisconnect) { if (p.N === undefined) { return; @@ -380,6 +369,10 @@ function Connect() { } Log("<" + escapeEntities(p.N) + "> " + p.M); + } else if (p.T == MessageChannels) { + allChannels = JSON.parse(p.M); + + updateChannelList(); } else if (p.T == MessageUsers) { var userListNew = '