using System;
using System.Collections.Generic;
using UnityEngine;
namespace Adrenak.UniVoice {
///
/// Handles a client session.
/// Requires an implementation of , and each.
/// Allows adding input and output filters and handles their execution.
///
///
public class ClientSession : IDisposable {
///
/// The instances of each peer in the session
///
public Dictionary PeerOutputs { get; private set; } = new Dictionary();
///
/// The input that will be applied to the outgoing audio for all the peers.
/// Note that filters are executed in the order they are present in this list
///
public List InputFilters { get; set; } = new List();
///
/// The output that will be applied to the incoming audio for all the peers.
/// Note that filters are executed in the order they are present in this list.
///
public List OutputFilters { get; set; } = new List();
public ClientSession(IAudioClient client, IAudioInput input, IAudioOutputFactory outputFactory) {
Client = client;
Input = input;
OutputFactory = outputFactory;
}
///
/// The that's used for networking
///
IAudioClient client;
public IAudioClient Client {
get => client;
set {
if(client != null)
client.Dispose();
client = value;
Client.OnLeft += () => {
foreach (var output in PeerOutputs)
output.Value.Dispose();
PeerOutputs.Clear();
};
Client.OnPeerJoined += id => {
try {
var output = outputFactory.Create();
PeerOutputs.Add(id, output);
}
catch (Exception e) {
Debug.LogException(e);
}
};
Client.OnPeerLeft += id => {
if (!PeerOutputs.ContainsKey(id))
return;
PeerOutputs[id].Dispose();
PeerOutputs.Remove(id);
};
client.OnReceivedPeerAudioFrame += (id, audioFrame) => {
if (!PeerOutputs.ContainsKey(id))
return;
if (OutputFilters != null) {
foreach (var filter in OutputFilters)
audioFrame = filter.Run(audioFrame);
}
if(audioFrame.samples.Length > 0)
PeerOutputs[id].Feed(audioFrame);
};
}
}
IAudioInput input;
///
/// The that's used for sourcing outgoing audio
///
public IAudioInput Input {
get => input;
set {
if(input != null)
input.Dispose();
input = value;
input.OnFrameReady += frame => {
if (InputFilters != null) {
foreach (var filter in InputFilters)
frame = filter.Run(frame);
}
if(frame.samples.Length > 0)
Client.SendAudioFrame(frame);
};
}
}
IAudioOutputFactory outputFactory;
///
/// The that creates the of peers
///
public IAudioOutputFactory OutputFactory {
get => outputFactory;
set {
outputFactory = value;
foreach (var output in PeerOutputs)
output.Value.Dispose();
PeerOutputs.Clear();
foreach (var id in Client.PeerIDs) {
try {
var output = outputFactory.Create();
PeerOutputs.Add(id, output);
}
catch (Exception e) {
Debug.LogException(e);
}
}
}
}
public void Dispose() {
Client.Dispose();
Input.Dispose();
}
}
}