context = window
ChannelGroupIds = context.JK.ChannelGroupIds
MixerActions = @MixerActions
ptrCount = 0
window.aggregate_latency_calc = (stats) -> `Total Latency is calculated as:
their gear output delay ({Math.round(stats.aggregate.their_out_latency)}ms)
+
your gear input delay ({Math.round(stats.aggregate.your_in_latency)}ms)
+internet delay ({Math.round(stats.aggregate.one_way)}ms)
+
delay caused by jitter queue ({Math.round(stats.aggregate.jq)}ms).`
StatsInfo = {
aggregate: {
latency: {
good: (user, stats) -> `{user.possessive} one-way, total latency from him to you is very good.
{window.aggregate_latency_calc(stats)}`,
warn: (user, stats) -> `{user.possessive} one-way, total latency from him to you is typical.
{window.aggregate_latency_calc(stats)}`,
poor: (user, stats) -> `{user.possessive} one-way, total latency from him to you is poor.
{window.aggregate_latency_calc(stats)}`
}
},
system: {
cpu: {
good: (user, stats) -> "#{user.possessive} computer processor is not overworked by JamKazam or the your system.",
warn: (user, stats) -> "#{user.possessive} computer processor is being heavily used. There is little spare capacity, and this means your processor may not be able to handle all of it's tasks, causing audio quality, latency, and other issues.",
poor: (user, stats) -> "#{user.possessive} computer processor is being very heavily used. There is little spare capacity, and this means your processor may not be able to handle all of it's tasks, causing audio quality, latency, and other issues."
}
},
network: {
wifi: {
good: (user, stats) -> "#{user.name} is using a wired connection.",
warn: (user, stats) -> "#{user.name} is using Wi-Fi, which will create audio quality issues and additional latency.",
poor: (user, stats) -> "#{user.name} is using Wi-Fi, which will create audio quality issues and additional latency.",
},
audio_bitrate_rx: {
good: (user, stats) -> "#{user.name} has enough bandwidth to send you a high quality audio stream.",
warn: (user, stats) -> "#{user.name} has enough bandwidth to send you a degraded, but sufficient, audio stream.",
poor: (user, stats) -> "#{user.name} has not enough bandwidth to send you a decent quality audio stream.",
},
audio_bitrate_tx: {
good: (user, stats) -> "You have enough bandwidth to send you a high quality audio stream.",
warn: (user, stats) -> "You have enough bandwidth to send you a degraded, but sufficient, audio stream.",
poor: (user, stats) -> "You have not enough bandwidth to send you a decent quality audio stream.",
},
video_rtpbw_rx: {
good: (user, stats) -> "#{user.name} has enough bandwidth to send you a high quality video stream.",
warn: (user, stats) -> "#{user.name} has enough bandwidth to send you a degraded, but sufficient, video stream.",
poor: (user, stats) -> "#{user.name} has not enough bandwidth to send you a decent quality video stream.",
},
video_rtpbw_tx: {
good: (user, stats) -> "You have enough bandwidth to send you a high quality video stream.",
warn: (user, stats) -> "You have enough bandwidth to send you a degraded, but sufficient, video stream.",
poor: (user, stats) -> "You have not enough bandwidth to send you a decent quality video stream.",
},
tx_ars_vs_p2p: {
good: (user, stats) -> "Your send network path is also the lowest latency path available",
warn: (user, stats) -> "Your send network path is not the lowest latency path available",
poor: (user, stats) -> "Your send network path is not the lowest latency path available",
},
rx_ars_vs_p2p: {
good: (user, stats) -> "Your receive network path is also the lowest latency path available",
warn: (user, stats) -> "Your receive network path is not the lowest latency path available",
poor: (user, stats) -> "Your receive network path is not the lowest latency path available",
},
ping: {
good: (user, stats) -> "The internet connection between you and #{user.name} has very low latency.",
warn: (user, stats) -> "The internet connection between you and #{user.name} has average latency, which may affect staying in sync.",
poor: (user, stats) -> "The internet connection between you and #{user.name} has high latency, making it very difficult to stay in sync.",
},
pkt_loss: {
good: (user, stats) -> "The internet connection between you and #{user.name} loses a small % of packets. It should not affect your audio quality.",
warn: (user, stats) -> "The internet connection between you and #{user.name} loses a significant % of packets. This may result in periodical audio artifacts.",
poor: (user, stats) -> "The internet connection between you and #{user.name} loses a high % of packets. This will result in frequent audio artifacts.",
},
audiojq_median: {
good: (user, stats) -> `JamKazam has to maintain a only a small buffer of audio to preserve audio quality, resulting in minimal added latency.
This buffer is adding {(2.5 * stats.network.audiojq_median).toFixed(1)}ms of latency.`,
warn: (user, stats) -> `JamKazam has to maintain a significant buffer of audio to preserve audio quality, resulting in potentially noticeable additional latency.
This buffer is adding {(2.5 * stats.network.audiojq_median).toFixed(1)}ms of latency.`,
poor: (user, stats) -> `JamKazam has to maintain a large buffer of audio to preserve audio quality, resulting in noticeabley added latency.
This buffer is adding {(2.5 * stats.network.audiojq_median).toFixed(1)}ms of latency.`,
}
},
audio: {
framesize: {
good: (user, stats) -> "#{user.possessive} gear is reading and writing audio data at a very high rate, keeping gear-added latency low.",
warn: (user, stats) -> "#{user.possessive} gear is reading and writing audio at a average rate, causing a few milliseconds extra latency compared to a 2.5 Frame Size.",
poor: (user, stats) -> "#{user.possessive} gear is reading and writing audio at a slow rate, causing a decent amount of latency before the internet is involved.",
},
latency: {
good: (user, stats) -> "#{user.possessive} gear has a small amount of latency.",
warn: (user, stats) -> "#{user.possessive} gear has a significant amount of latency.",
poor: (user, stats) -> "#{user.possessive} gear has a large amount of latency, making it difficult to play in time."
},
input_jitter: {
good: (user, stats) -> "#{user.possessive} gear has a small amount of input jitter, meaning it is keeping good time with JamKazam as it reads in your input signal.",
warn: (user, stats) -> "#{user.possessive} gear has a significant amount of input jitter, meaning it might be periodically adding delay or audio artifacts to your inputs.",
poor: (user, stats) -> "#{user.possessive} gear has a large amount of input jitter, meaning it likely adding delay and audio artifacts to your inputs.",
},
output_jitter: {
good: (user, stats) -> "#{user.possessive} gear has a small amount of output jitter, meaning it is keeping good time with your JamKazam as writes out your audio output.",
warn: (user, stats) -> "#{user.possessive} gear has a significant amount of output jitter, meaning it might be periodically adding delay and audio artifacts to your output.",
poor: (user, stats) -> "#{user.possessive} gear has a large amount of output jitter, meaning it likely adding delay and audio artifacts to your output.",
},
audio_in_type: {
good: (user, stats) -> "#{user.name} using an ideal driver type for #{user.possessive.toLowerCase()} gear.",
warn: (user, stats) -> "#{user.name} using a problematic driver type for #{user.possessive.toLowerCase()} gear.",
poor: (user, stats) -> "#{user.name} using a driver type considered problematic.",
}
}
}
@SessionStatsHover = React.createClass({
propTypes: {
clientId: React.PropTypes.string
}
mixins: [Reflux.listenTo(@SessionStatsStore, "onStatsChanged")]
hover: (type, field) ->
logger.debug("hover! #{type} #{field}")
@setState({hoverType: type, hoverField:field})
hoverOut: () ->
logger.debug("hover out!")
@setState({hoverType: null, hoverField: null})
stat: (properties, type, name, field, value) ->
classes = {'status-icon': true}
classifier = properties[field + '_level']
classes[classifier] = true
`