2012-10-06 16:36:05 +00:00
|
|
|
(function(context,$) {
|
|
|
|
|
|
2012-12-07 00:28:48 +00:00
|
|
|
"use strict";
|
|
|
|
|
|
2012-10-06 16:36:05 +00:00
|
|
|
context.JK = context.JK || {};
|
|
|
|
|
context.JK.SessionScreen = function(app) {
|
2012-10-14 15:48:56 +00:00
|
|
|
var logger = context.JK.logger;
|
2013-03-02 19:02:42 +00:00
|
|
|
var sessionModel = null;
|
2012-10-29 15:10:02 +00:00
|
|
|
var sessionId;
|
2012-10-22 02:55:05 +00:00
|
|
|
var tracks = {};
|
2013-01-30 16:50:43 +00:00
|
|
|
var mixers = [];
|
2013-03-02 19:02:42 +00:00
|
|
|
|
2013-02-26 03:54:09 +00:00
|
|
|
// TODO Consolidate dragged controls and handles
|
2013-02-03 19:48:39 +00:00
|
|
|
var $draggingFaderHandle = null;
|
2013-02-03 17:50:26 +00:00
|
|
|
var $draggingFader = null;
|
2013-02-07 04:58:41 +00:00
|
|
|
var $draggingVolumeHandle = null;
|
|
|
|
|
var $draggingVolume = null;
|
2013-02-08 05:08:05 +00:00
|
|
|
var $draggingChatHandle = null;
|
|
|
|
|
var $draggingChat = null;
|
2013-03-15 02:44:51 +00:00
|
|
|
var currentMixerIds = null;
|
2013-02-03 22:47:17 +00:00
|
|
|
var currentMixerRangeMin = null;
|
|
|
|
|
var currentMixerRangeMax = null;
|
2012-10-06 16:36:05 +00:00
|
|
|
|
2013-02-14 07:02:05 +00:00
|
|
|
var lookingForMixersCount = 0;
|
|
|
|
|
var lookingForMixersTimer = null;
|
|
|
|
|
var lookingForMixers = {};
|
|
|
|
|
|
2013-02-05 05:10:37 +00:00
|
|
|
var defaultParticipant = {
|
2013-02-10 00:33:47 +00:00
|
|
|
tracks: [{
|
|
|
|
|
instrument_id: "unknown"
|
|
|
|
|
}],
|
2013-02-05 05:10:37 +00:00
|
|
|
user: {
|
|
|
|
|
first_name: 'Unknown',
|
|
|
|
|
last_name: 'User',
|
|
|
|
|
photo_url: null
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2013-03-01 05:04:42 +00:00
|
|
|
var instrumentIcons = context.JK.getInstrumentIconMap45();
|
2013-02-26 03:54:09 +00:00
|
|
|
|
|
|
|
|
// Recreate ChannelGroupIDs ENUM from C++
|
|
|
|
|
var ChannelGroupIds = {
|
|
|
|
|
"MasterGroup": 0,
|
|
|
|
|
"MonitorGroup": 1,
|
|
|
|
|
"AudioInputMusicGroup": 2,
|
|
|
|
|
"AudioInputChatGroup": 3,
|
|
|
|
|
"MediaTrackGroup": 4,
|
|
|
|
|
"StreamOutMusicGroup": 5,
|
|
|
|
|
"StreamOutChatGroup": 6,
|
|
|
|
|
"UserMusicInputGroup": 7,
|
|
|
|
|
"UserChatInputGroup": 8,
|
|
|
|
|
"PeerAudioInputMusicGroup": 9
|
|
|
|
|
};
|
2013-02-05 05:10:37 +00:00
|
|
|
|
2012-10-29 15:10:02 +00:00
|
|
|
function beforeShow(data) {
|
|
|
|
|
sessionId = data.id;
|
2013-02-06 04:32:56 +00:00
|
|
|
$('#session-mytracks-container').empty();
|
|
|
|
|
$('#session-livetracks-container').empty();
|
2012-10-29 15:10:02 +00:00
|
|
|
}
|
2012-10-29 00:37:59 +00:00
|
|
|
|
2012-10-06 16:36:05 +00:00
|
|
|
function afterShow(data) {
|
2013-01-30 16:50:43 +00:00
|
|
|
// Subscribe for callbacks on audio events
|
|
|
|
|
context.jamClient.SessionRegisterCallback("JK.HandleBridgeCallback");
|
2012-10-29 00:37:59 +00:00
|
|
|
|
2013-02-26 03:54:09 +00:00
|
|
|
// If you load this page directly, the loading of the current user
|
|
|
|
|
// is happening in parallel. We can't join the session until the
|
|
|
|
|
// current user has been completely loaded. Poll for the current user
|
|
|
|
|
// before proceeding with session joining.
|
|
|
|
|
function checkForCurrentUser() {
|
|
|
|
|
if (context.JK.userMe) {
|
|
|
|
|
logger.debug("current user loaded. Proceeding to join session.");
|
|
|
|
|
afterCurrentUserLoaded();
|
|
|
|
|
} else {
|
|
|
|
|
logger.debug("Current user not loaded yet. Waiting...");
|
|
|
|
|
context.setTimeout(checkForCurrentUser, 100);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
checkForCurrentUser();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function afterCurrentUserLoaded() {
|
2013-03-02 19:02:42 +00:00
|
|
|
sessionModel = new context.JK.SessionModel(
|
|
|
|
|
context.JK.JamServer,
|
|
|
|
|
context.jamClient,
|
|
|
|
|
context.JK.userMe
|
|
|
|
|
);
|
|
|
|
|
sessionModel.subscribe('sessionScreen', sessionChanged);
|
|
|
|
|
sessionModel.joinSession(sessionId);
|
2013-02-10 18:51:37 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-29 00:37:59 +00:00
|
|
|
function beforeHide(data) {
|
2013-03-02 19:02:42 +00:00
|
|
|
sessionModel.leaveCurrentSession(sessionId);
|
2013-01-31 05:23:30 +00:00
|
|
|
// 'unregister' for callbacks
|
|
|
|
|
context.jamClient.SessionRegisterCallback("");
|
2012-10-06 16:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-02 19:02:42 +00:00
|
|
|
function sessionChanged() {
|
|
|
|
|
renderSession();
|
2012-11-03 20:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderSession() {
|
2013-02-14 07:02:05 +00:00
|
|
|
$('#session-mytracks-container').empty();
|
|
|
|
|
$('#session-livetracks-container').empty();
|
2013-01-30 16:50:43 +00:00
|
|
|
_updateMixers();
|
2012-11-03 20:25:23 +00:00
|
|
|
_renderTracks();
|
2013-02-07 04:58:41 +00:00
|
|
|
_wireTopVolume();
|
|
|
|
|
_addVoiceChat();
|
2013-01-30 16:50:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the latest list of underlying audio mixer channels
|
|
|
|
|
function _updateMixers() {
|
2013-01-31 16:32:32 +00:00
|
|
|
var mixerIds = context.jamClient.SessionGetIDs();
|
2013-02-05 05:10:37 +00:00
|
|
|
var holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(mixerIds)});
|
|
|
|
|
mixers = holder.mixers;
|
2012-10-21 23:03:46 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-14 07:02:05 +00:00
|
|
|
function _mixerForClientId(clientId, groupIds) {
|
|
|
|
|
var foundMixer = null;
|
|
|
|
|
$.each(mixers, function(index, mixer) {
|
|
|
|
|
if (mixer.client_id === clientId) {
|
|
|
|
|
for (var i=0; i<groupIds.length; i++) {
|
|
|
|
|
if (mixer.group_id === groupIds[i]) {
|
|
|
|
|
foundMixer = mixer;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-02-05 05:10:37 +00:00
|
|
|
}
|
|
|
|
|
});
|
2013-02-14 07:02:05 +00:00
|
|
|
return foundMixer;
|
2013-01-30 16:50:43 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-07 04:58:41 +00:00
|
|
|
function _wireTopVolume() {
|
|
|
|
|
var $volumeSlider = $('#volume');
|
2013-03-14 03:29:57 +00:00
|
|
|
var mixerIds = [];
|
2013-02-07 04:58:41 +00:00
|
|
|
$.each(mixers, function(index, mixer) {
|
2013-02-26 03:54:09 +00:00
|
|
|
if (mixer.group_id === ChannelGroupIds.MasterGroup) {
|
2013-03-14 03:29:57 +00:00
|
|
|
mixerIds.push(mixer.id);
|
2013-02-13 05:30:07 +00:00
|
|
|
var gainPercent = percentFromMixerValue(
|
|
|
|
|
mixer.range_low, mixer.range_high, mixer.volume_left);
|
|
|
|
|
$volumeSlider.find('.slider-volume').css('left', gainPercent + '%');
|
2013-02-07 04:58:41 +00:00
|
|
|
}
|
2013-02-26 03:54:09 +00:00
|
|
|
if (mixer.group_id === ChannelGroupIds.MonitorGroup) {
|
2013-03-14 03:29:57 +00:00
|
|
|
mixerIds.push(mixer.id);
|
2013-02-07 04:58:41 +00:00
|
|
|
}
|
|
|
|
|
});
|
2013-03-14 03:29:57 +00:00
|
|
|
$volumeSlider.attr('mixer-id', mixerIds.join(','));
|
2013-02-07 04:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _addVoiceChat() {
|
2013-02-08 05:08:05 +00:00
|
|
|
// If, and only if, there is a mixer in group 3 (voice chat)
|
|
|
|
|
// Add the voice chat controls below my tracks, and hook up the mixer.
|
|
|
|
|
// Assumption is that there is only ever one, so we just take the first one.
|
|
|
|
|
$.each(mixers, function(index, mixer) {
|
2013-02-26 03:54:09 +00:00
|
|
|
if (mixer.group_id === ChannelGroupIds.AudioInputChatGroup) {
|
2013-02-08 05:08:05 +00:00
|
|
|
var $voiceChat = $('#voice-chat');
|
|
|
|
|
$voiceChat.show();
|
|
|
|
|
$voiceChat.attr('mixer-id', mixer.id);
|
|
|
|
|
$('#voice-chat .voicechat-mute').attr('mixer-id', mixer.id);
|
2013-02-13 05:30:07 +00:00
|
|
|
|
|
|
|
|
var gainPercent = percentFromMixerValue(
|
|
|
|
|
mixer.range_low, mixer.range_high, mixer.volume_left);
|
|
|
|
|
$voiceChat.find('.voicechat-gain-slider').css({'left': gainPercent + '%'});
|
|
|
|
|
if (mixer.mute) {
|
|
|
|
|
var $mute = $voiceChat.find('.voicechat-mute');
|
|
|
|
|
_toggleVisualMuteControl($mute, true);
|
|
|
|
|
}
|
2013-02-08 05:08:05 +00:00
|
|
|
}
|
|
|
|
|
});
|
2013-02-07 04:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-10 00:33:47 +00:00
|
|
|
function _instrumentIconFromId(id) {
|
|
|
|
|
if (id in instrumentIcons) {
|
|
|
|
|
return instrumentIcons[id];
|
|
|
|
|
}
|
|
|
|
|
// return default instrument for any unknowns
|
|
|
|
|
return "content/icon_instrument_default45.png";
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 20:25:23 +00:00
|
|
|
function _renderTracks() {
|
2013-02-14 07:02:05 +00:00
|
|
|
// Participants are here now, but the mixers don't update right away.
|
|
|
|
|
// Draw tracks from participants, then setup timers to look for the
|
|
|
|
|
// mixers that go with those participants, if they're missing.
|
|
|
|
|
lookingForMixersCount = 0;
|
2013-03-02 19:02:42 +00:00
|
|
|
$.each(sessionModel.participants(), function(index, participant) {
|
2013-02-14 07:02:05 +00:00
|
|
|
|
|
|
|
|
var name = participant.user.name;
|
|
|
|
|
if (!(name)) {
|
|
|
|
|
name = participant.user.first_name + ' ' + participant.user.last_name;
|
|
|
|
|
}
|
|
|
|
|
var instrumentIcon = _instrumentIconFromId(participant.tracks[0].instrument_id);
|
2013-03-01 04:38:15 +00:00
|
|
|
var photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
|
2013-02-14 07:02:05 +00:00
|
|
|
|
|
|
|
|
var myTrack = false;
|
|
|
|
|
|
|
|
|
|
// Default trackData to participant + no Mixer state.
|
|
|
|
|
var trackData = {
|
|
|
|
|
clientId: participant.client_id,
|
|
|
|
|
name: name,
|
|
|
|
|
instrumentIcon: instrumentIcon,
|
|
|
|
|
avatar: photoUrl,
|
|
|
|
|
latency: "good",
|
|
|
|
|
gainPercent: 0,
|
|
|
|
|
muteClass: 'muted',
|
|
|
|
|
mixerId: ""
|
|
|
|
|
};
|
|
|
|
|
|
2013-02-26 03:54:09 +00:00
|
|
|
var mixer = _mixerForClientId(
|
|
|
|
|
participant.client_id,
|
|
|
|
|
[
|
|
|
|
|
ChannelGroupIds.AudioInputMusicGroup,
|
|
|
|
|
ChannelGroupIds.UserMusicInputGroup
|
|
|
|
|
]);
|
2013-02-14 07:02:05 +00:00
|
|
|
if (mixer) {
|
2013-02-26 03:54:09 +00:00
|
|
|
myTrack = (mixer.group_id === ChannelGroupIds.AudioInputMusicGroup);
|
2013-02-10 02:00:29 +00:00
|
|
|
var gainPercent = percentFromMixerValue(
|
|
|
|
|
mixer.range_low, mixer.range_high, mixer.volume_left);
|
|
|
|
|
var muteClass = "enabled";
|
|
|
|
|
if (mixer.mute) {
|
|
|
|
|
muteClass = "muted";
|
|
|
|
|
}
|
2013-02-14 07:02:05 +00:00
|
|
|
trackData.gainPercent = gainPercent;
|
|
|
|
|
trackData.muteClass = muteClass;
|
|
|
|
|
trackData.mixerId = mixer.id;
|
|
|
|
|
} else { // No mixer to match, yet
|
|
|
|
|
lookingForMixers[participant.client_id] = true;
|
|
|
|
|
if (!(lookingForMixersTimer)) {
|
|
|
|
|
lookingForMixersTimer = context.setInterval(lookForMixers, 300);
|
2013-02-10 00:33:47 +00:00
|
|
|
}
|
2012-11-03 20:25:23 +00:00
|
|
|
}
|
2013-02-14 07:02:05 +00:00
|
|
|
_addTrack(trackData);
|
|
|
|
|
// Show settings icons only for my tracks
|
|
|
|
|
if (myTrack) {
|
|
|
|
|
$('div[mixer-id="' + mixer.id + '"].track-icon-settings').show();
|
|
|
|
|
}
|
2012-11-03 20:25:23 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-14 07:02:05 +00:00
|
|
|
// Function called on an interval when participants change. Mixers seem to
|
|
|
|
|
// show up later, so we render the tracks from participants, but keep track
|
|
|
|
|
// of the ones there weren't any mixers for, and continually try to find them
|
|
|
|
|
// and get them connected to the mixers underneath.
|
|
|
|
|
function lookForMixers() {
|
|
|
|
|
lookingForMixersCount++;
|
|
|
|
|
_updateMixers();
|
|
|
|
|
var keysToDelete = [];
|
|
|
|
|
for (var key in lookingForMixers) {
|
2013-02-26 03:54:09 +00:00
|
|
|
var mixer = _mixerForClientId(
|
|
|
|
|
key,
|
|
|
|
|
[
|
|
|
|
|
ChannelGroupIds.AudioInputMusicGroup,
|
|
|
|
|
ChannelGroupIds.UserMusicInputGroup
|
|
|
|
|
]);
|
2013-02-14 07:02:05 +00:00
|
|
|
if (mixer) {
|
|
|
|
|
keysToDelete.push(key);
|
|
|
|
|
var gainPercent = percentFromMixerValue(
|
|
|
|
|
mixer.range_low, mixer.range_high, mixer.volume_left);
|
|
|
|
|
var $track = $('div.track[client-id="' + key + '"]');
|
|
|
|
|
// Set mixer-id attributes
|
2013-02-15 05:15:36 +00:00
|
|
|
$track.find('.track-vu-left').attr('mixer-id', mixer.id + "_vul");
|
|
|
|
|
$track.find('.track-vu-right').attr('mixer-id', mixer.id + "_vur");
|
2013-02-14 07:02:05 +00:00
|
|
|
$track.find('.track-gain').attr('mixer-id', mixer.id);
|
|
|
|
|
$track.find('.track-icon-mute').attr('mixer-id', mixer.id);
|
|
|
|
|
$track.find('.track-icon-settings').attr('mixer-id', mixer.id);
|
|
|
|
|
|
|
|
|
|
// Set gain position
|
|
|
|
|
$track.find('.track-gain-slider').css('bottom', gainPercent + '%');
|
|
|
|
|
|
|
|
|
|
// Set mute state
|
|
|
|
|
_toggleVisualMuteControl($track.find('.track-icon-mute'), mixer.mute);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i=0; i<keysToDelete.length; i++) {
|
|
|
|
|
delete lookingForMixers[keysToDelete[i]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context.JK.dlen(lookingForMixers) === 0 ||
|
|
|
|
|
lookingForMixersCount > 10) {
|
|
|
|
|
lookingForMixersCount = 0;
|
|
|
|
|
lookingForMixers = {};
|
|
|
|
|
context.clearTimeout(lookingForMixersTimer);
|
|
|
|
|
lookingForMixersTimer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-30 16:50:43 +00:00
|
|
|
// Given a mixerID and a value between 0.0-1.0,
|
|
|
|
|
// light up the proper VU lights.
|
|
|
|
|
function _updateVU(mixerId, value) {
|
2013-01-31 16:32:32 +00:00
|
|
|
// Minor tweak to support VU values -- the mixerId here will
|
|
|
|
|
// have a suffix added _vul or _vur to indicate the channel.
|
2013-01-30 16:50:43 +00:00
|
|
|
// There are 13 VU lights. Figure out how many to
|
|
|
|
|
// light based on the incoming value.
|
|
|
|
|
var i = 0;
|
|
|
|
|
var state = 'on';
|
|
|
|
|
var lights = Math.round(13 * value);
|
|
|
|
|
var selector = null;
|
|
|
|
|
var $light = null;
|
|
|
|
|
var colorClass = 'vu-green-';
|
|
|
|
|
// Remove all light classes from all lights
|
2013-01-31 16:32:32 +00:00
|
|
|
var allLightsSelector = '#tracks table[mixer-id="' + mixerId + '"] td.vulight';
|
2013-01-30 16:50:43 +00:00
|
|
|
$(allLightsSelector).removeClass('vu-green-off vu-green-on vu-red-off vu-red-on');
|
|
|
|
|
|
|
|
|
|
// Set the lights
|
|
|
|
|
for (i=0; i<13; i++) {
|
|
|
|
|
colorClass = 'vu-green-';
|
|
|
|
|
state = 'on';
|
|
|
|
|
if (i > 8) {
|
|
|
|
|
colorClass = 'vu-red-';
|
|
|
|
|
}
|
|
|
|
|
if (i >= lights) {
|
|
|
|
|
state = 'off';
|
|
|
|
|
}
|
2013-01-31 16:32:32 +00:00
|
|
|
selector = '#tracks table[mixer-id="' + mixerId + '"] td.vu' + i;
|
2013-01-30 16:50:43 +00:00
|
|
|
$light = $(selector);
|
|
|
|
|
$light.addClass(colorClass + state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-21 23:03:46 +00:00
|
|
|
function _addTrack(trackData) {
|
2013-02-05 05:10:37 +00:00
|
|
|
var $destination = $('#session-mytracks-container');
|
|
|
|
|
if (trackData.clientId !== app.clientId) {
|
|
|
|
|
$destination = $('#session-livetracks-container');
|
|
|
|
|
}
|
2013-01-29 16:30:45 +00:00
|
|
|
trackData["left-vu"] = $('#template-vu').html();
|
|
|
|
|
trackData["right-vu"] = trackData["left-vu"];
|
2012-10-21 23:03:46 +00:00
|
|
|
var template = $('#template-session-track').html();
|
2012-12-07 00:28:48 +00:00
|
|
|
var newTrack = context.JK.fillTemplate(template, trackData);
|
2013-02-05 05:10:37 +00:00
|
|
|
$destination.append(newTrack);
|
2012-12-07 00:28:48 +00:00
|
|
|
tracks[trackData.clientId] = new context.JK.SessionTrack(trackData.clientId);
|
2012-10-21 23:03:46 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-31 05:23:30 +00:00
|
|
|
function handleBridgeCallback() {
|
|
|
|
|
var eventName = null;
|
|
|
|
|
var mixerId = null;
|
|
|
|
|
var value = null;
|
|
|
|
|
var tuples = arguments.length / 3;
|
|
|
|
|
for (var i=0; i<tuples; i++) {
|
|
|
|
|
eventName = arguments[3*i];
|
|
|
|
|
mixerId = arguments[(3*i)+1];
|
|
|
|
|
value = arguments[(3*i)+2];
|
|
|
|
|
var vuVal = 0.0;
|
|
|
|
|
if (eventName === 'left_vu' || eventName === 'right_vu') {
|
|
|
|
|
// TODO - no guarantee range will be -80 to 20. Get from the
|
|
|
|
|
// GetControlState for this mixer which returns min/max
|
|
|
|
|
// value is a DB value from -80 to 20. Convert to float from 0.0-1.0
|
|
|
|
|
vuVal = (value + 80) / 100;
|
|
|
|
|
if (eventName === 'left_vu') {
|
2013-01-31 16:32:32 +00:00
|
|
|
mixerId = mixerId + "_vul";
|
2013-01-31 05:23:30 +00:00
|
|
|
} else {
|
2013-01-31 16:32:32 +00:00
|
|
|
mixerId = mixerId + "_vur";
|
2013-01-31 05:23:30 +00:00
|
|
|
}
|
|
|
|
|
_updateVU(mixerId, vuVal);
|
2013-02-15 05:15:36 +00:00
|
|
|
} else if (eventName === 'add' || eventName === 'remove') {
|
|
|
|
|
// TODO - _renderSession. Note I get streams of these in
|
|
|
|
|
// sequence, so have Nat fix, or buffer/spam protect
|
|
|
|
|
// Note - this is already handled from websocket events.
|
|
|
|
|
// However, there may be use of these two events to avoid
|
|
|
|
|
// the polling-style check for when a mixer has been added
|
|
|
|
|
// to match a participant track.
|
2013-01-31 16:32:32 +00:00
|
|
|
} else {
|
|
|
|
|
// Examples of other events
|
|
|
|
|
// Add media file track: "add", "The_Abyss_4T", 0
|
|
|
|
|
logger.debug('non-vu event: ' + eventName + ',' + mixerId + ',' + value);
|
2013-01-31 05:23:30 +00:00
|
|
|
}
|
2013-01-30 16:50:43 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-06 16:36:05 +00:00
|
|
|
function deleteSession(evt) {
|
2012-12-07 00:28:48 +00:00
|
|
|
var sessionId = $(evt.currentTarget).attr("action-id");
|
2012-10-06 16:36:05 +00:00
|
|
|
if (sessionId) {
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: "DELETE",
|
2013-02-26 03:54:09 +00:00
|
|
|
url: "/api/sessions/" + sessionId,
|
|
|
|
|
success: function(response) {
|
|
|
|
|
context.location="#/home";
|
|
|
|
|
},
|
|
|
|
|
error: function(jqXHR, textStatus, errorThrown) {
|
|
|
|
|
logger.error("Error deleting session " + sessionId);
|
|
|
|
|
}
|
|
|
|
|
});
|
2012-10-06 16:36:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-31 16:32:32 +00:00
|
|
|
function _toggleVisualMuteControl($control, muting) {
|
|
|
|
|
if (muting) {
|
|
|
|
|
$control.removeClass('enabled');
|
|
|
|
|
$control.addClass('muted');
|
|
|
|
|
} else {
|
|
|
|
|
$control.removeClass('muted');
|
|
|
|
|
$control.addClass('enabled');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _toggleAudioMute(mixerId, muting) {
|
2013-03-15 02:44:51 +00:00
|
|
|
fillTrackVolumeObject(mixerId);
|
2013-01-31 16:32:32 +00:00
|
|
|
context.trackVolumeObject.mute = muting;
|
|
|
|
|
context.jamClient.SessionSetControlState(mixerId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toggleMute(evt) {
|
|
|
|
|
var $control = $(evt.currentTarget);
|
|
|
|
|
var muting = ($control.hasClass('enabled'));
|
2013-03-15 02:44:51 +00:00
|
|
|
var mixerIds = $control.attr('mixer-id').split(',');
|
|
|
|
|
$.each(mixerIds, function(i,v) {
|
|
|
|
|
_toggleAudioMute(v, muting);
|
|
|
|
|
});
|
2013-01-31 16:32:32 +00:00
|
|
|
_toggleVisualMuteControl($control, muting);
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-10 00:33:47 +00:00
|
|
|
function getVerticalFaderPercent(eventY, $fader) {
|
2013-03-15 02:44:51 +00:00
|
|
|
return getFaderPercent(eventY, $fader, 'vertical');
|
2013-02-03 19:48:39 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-07 04:58:41 +00:00
|
|
|
function getHorizontalFaderPercent(eventX, $fader) {
|
2013-03-15 02:44:51 +00:00
|
|
|
return getFaderPercent(eventX, $fader, 'horizontal');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getFaderPercent(value, $fader, orientation) {
|
2013-02-07 04:58:41 +00:00
|
|
|
var faderPosition = $fader.offset();
|
2013-03-15 02:44:51 +00:00
|
|
|
var faderMin = faderPosition.top;
|
|
|
|
|
var faderSize = $fader.height();
|
|
|
|
|
var handleValue = (faderSize - (value-faderMin));
|
|
|
|
|
if (orientation === "horizontal") {
|
|
|
|
|
faderMin = faderPosition.left;
|
|
|
|
|
faderSize = $fader.width();
|
|
|
|
|
handleValue = (value - faderMin);
|
|
|
|
|
}
|
|
|
|
|
var faderPct = Math.round(handleValue/faderSize * 100);
|
2013-02-07 04:58:41 +00:00
|
|
|
if (faderPct < 0) {
|
|
|
|
|
faderPct = 0;
|
|
|
|
|
}
|
|
|
|
|
if (faderPct > 100) {
|
|
|
|
|
faderPct = 100;
|
|
|
|
|
}
|
|
|
|
|
return faderPct;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-03 22:47:17 +00:00
|
|
|
function fillTrackVolumeObject(mixerId) {
|
2013-03-15 02:44:51 +00:00
|
|
|
_updateMixers();
|
2013-02-03 22:47:17 +00:00
|
|
|
var mixer = null;
|
|
|
|
|
for (var i=0; i<mixers.length; i++) {
|
|
|
|
|
mixer = mixers[i];
|
|
|
|
|
if (mixer.id === mixerId) {
|
|
|
|
|
context.trackVolumeObject.clientID = mixer.client_id;
|
|
|
|
|
context.trackVolumeObject.master = mixer.master;
|
|
|
|
|
context.trackVolumeObject.monitor = mixer.monitor;
|
|
|
|
|
context.trackVolumeObject.mute = mixer.mute;
|
|
|
|
|
context.trackVolumeObject.name = mixer.name;
|
|
|
|
|
context.trackVolumeObject.record = mixer.record;
|
|
|
|
|
context.trackVolumeObject.volL = mixer.volume_left;
|
|
|
|
|
context.trackVolumeObject.volR = mixer.volume_right;
|
|
|
|
|
// trackVolumeObject doesn't have a place for range min/max
|
|
|
|
|
currentMixerRangeMin = mixer.range_low;
|
|
|
|
|
currentMixerRangeMax = mixer.range_high;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-10 02:00:29 +00:00
|
|
|
// Given a mixer's min/max and current value, return it as
|
|
|
|
|
// a percent from 0-100. Return an integer.
|
|
|
|
|
function percentFromMixerValue(min, max, value) {
|
|
|
|
|
var range = Math.abs(max - min);
|
|
|
|
|
var magnitude = value - min;
|
|
|
|
|
var percent = Math.round(100*(magnitude/range));
|
|
|
|
|
return percent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given a mixer's min/max and a percent value, return it as
|
|
|
|
|
// the mixer's value. Returns an integer.
|
|
|
|
|
function percentToMixerValue(min, max, percent) {
|
|
|
|
|
var range = Math.abs(max - min);
|
|
|
|
|
var multiplier = percent/100; // Change 85 into 0.85
|
|
|
|
|
var value = min + (multiplier * range);
|
|
|
|
|
// Protect against percents < 0 and > 100
|
|
|
|
|
if (value < min) {
|
|
|
|
|
value = min;
|
|
|
|
|
}
|
|
|
|
|
if (value > max) {
|
|
|
|
|
value = max;
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2013-02-03 22:47:17 +00:00
|
|
|
|
2013-02-10 02:00:29 +00:00
|
|
|
// Given a volume percent (0-100), set the underlying
|
2013-02-03 19:48:39 +00:00
|
|
|
// audio volume level of the passed mixerId to the correct
|
|
|
|
|
// value.
|
|
|
|
|
function setMixerVolume(mixerId, volumePercent) {
|
2013-02-03 22:47:17 +00:00
|
|
|
// The context.trackVolumeObject has been filled with the mixer values
|
|
|
|
|
// that go with mixerId, and the range of that mixer
|
|
|
|
|
// has been set in currentMixerRangeMin-Max.
|
|
|
|
|
// All that needs doing is to translate the incoming percent
|
|
|
|
|
// into the real value ont the sliders range. Set Left/Right
|
|
|
|
|
// volumes on trackVolumeObject, and call SetControlState to stick.
|
2013-02-10 02:00:29 +00:00
|
|
|
var sliderValue = percentToMixerValue(
|
|
|
|
|
currentMixerRangeMin, currentMixerRangeMax, volumePercent);
|
2013-02-03 22:47:17 +00:00
|
|
|
context.trackVolumeObject.volL = sliderValue;
|
|
|
|
|
context.trackVolumeObject.volR = sliderValue;
|
|
|
|
|
context.jamClient.SessionSetControlState(mixerId);
|
2013-02-03 19:48:39 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-03 00:16:12 +00:00
|
|
|
|
2013-02-08 05:08:05 +00:00
|
|
|
// Refactor. Only need one of these xxxDown methods.
|
2013-02-03 17:50:26 +00:00
|
|
|
function faderHandleDown(evt) {
|
|
|
|
|
evt.stopPropagation();
|
2013-02-03 19:48:39 +00:00
|
|
|
$draggingFaderHandle = $(evt.currentTarget);
|
|
|
|
|
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
|
2013-03-15 02:44:51 +00:00
|
|
|
currentMixerIds = $draggingFader.closest('[mixer-id]').attr('mixer-id').split(',');
|
|
|
|
|
var mixerIds = currentMixerIds;
|
|
|
|
|
$.each(mixerIds, function(i,v) {
|
|
|
|
|
fillTrackVolumeObject(v);
|
|
|
|
|
});
|
2013-02-08 05:08:05 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-15 02:44:51 +00:00
|
|
|
function faderMouseUp(evt) {
|
2013-02-03 19:48:39 +00:00
|
|
|
evt.stopPropagation();
|
|
|
|
|
if ($draggingFaderHandle) {
|
|
|
|
|
$draggingFaderHandle = null;
|
2013-02-03 17:50:26 +00:00
|
|
|
$draggingFader = null;
|
2013-03-15 02:44:51 +00:00
|
|
|
currentMixerIds = null;
|
2013-02-08 05:08:05 +00:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-15 02:44:51 +00:00
|
|
|
function faderMouseMove(evt) {
|
2013-02-03 19:48:39 +00:00
|
|
|
// bail out early if there's no in-process drag
|
|
|
|
|
if (!($draggingFaderHandle)) {
|
|
|
|
|
return false;
|
2013-02-03 17:50:26 +00:00
|
|
|
}
|
2013-03-15 02:44:51 +00:00
|
|
|
var $fader = $draggingFader;
|
|
|
|
|
var $handle = $draggingFaderHandle;
|
2013-02-03 19:48:39 +00:00
|
|
|
evt.stopPropagation();
|
2013-03-15 02:44:51 +00:00
|
|
|
var orientation = $fader.attr('orientation');
|
|
|
|
|
var getPercentFunction = getVerticalFaderPercent;
|
|
|
|
|
var absolutePosition = evt.clientY;
|
|
|
|
|
var handleCssAttribute = 'bottom';
|
|
|
|
|
if (orientation && orientation == 'horizontal') {
|
|
|
|
|
getPercentFunction = getHorizontalFaderPercent;
|
|
|
|
|
absolutePosition = evt.clientX;
|
|
|
|
|
handleCssAttribute = 'left';
|
2013-02-08 05:08:05 +00:00
|
|
|
}
|
2013-03-15 02:44:51 +00:00
|
|
|
var faderPct = getPercentFunction(absolutePosition, $fader);
|
|
|
|
|
var mixerIds = currentMixerIds;
|
|
|
|
|
$.each(mixerIds, function(i,v) {
|
|
|
|
|
setMixerVolume(v, faderPct);
|
|
|
|
|
});
|
2013-02-08 05:08:05 +00:00
|
|
|
if (faderPct > 90) { faderPct = 90; } // Visual limit
|
2013-03-15 02:44:51 +00:00
|
|
|
$handle.css(handleCssAttribute, faderPct + '%');
|
2013-02-07 04:58:41 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-08 05:08:05 +00:00
|
|
|
function faderClick(evt) {
|
2013-02-07 04:58:41 +00:00
|
|
|
evt.stopPropagation();
|
2013-02-08 05:08:05 +00:00
|
|
|
if ($draggingFaderHandle) {
|
|
|
|
|
return;
|
2013-02-07 04:58:41 +00:00
|
|
|
}
|
2013-02-08 05:08:05 +00:00
|
|
|
var $fader = $(evt.currentTarget);
|
2013-02-07 04:58:41 +00:00
|
|
|
|
2013-03-14 03:29:57 +00:00
|
|
|
// Switch based on fader orientation
|
|
|
|
|
var orientation = $fader.attr('orientation');
|
|
|
|
|
var getPercentFunction = getVerticalFaderPercent;
|
|
|
|
|
var absolutePosition = evt.clientY;
|
|
|
|
|
var handleCssAttribute = 'bottom';
|
|
|
|
|
if (orientation && orientation == 'horizontal') {
|
|
|
|
|
getPercentFunction = getHorizontalFaderPercent;
|
|
|
|
|
absolutePosition = evt.clientX;
|
|
|
|
|
handleCssAttribute = 'left';
|
2013-02-07 04:58:41 +00:00
|
|
|
}
|
2013-02-08 05:08:05 +00:00
|
|
|
|
2013-03-14 03:29:57 +00:00
|
|
|
var $handle = $fader.find('div[control="fader-handle"]');
|
|
|
|
|
var faderPct = getPercentFunction(absolutePosition, $fader);
|
|
|
|
|
// mixerIds can be a comma-separated list
|
|
|
|
|
var mixerIds = $fader.closest('[mixer-id]').attr('mixer-id').split(',');
|
|
|
|
|
$.each(mixerIds, function(i,v) {
|
|
|
|
|
fillTrackVolumeObject(v);
|
|
|
|
|
setMixerVolume(v, faderPct);
|
|
|
|
|
});
|
2013-02-07 04:58:41 +00:00
|
|
|
if (faderPct > 90) { faderPct = 90; } // Visual limit
|
2013-03-14 03:29:57 +00:00
|
|
|
$handle.css(handleCssAttribute, faderPct + '%');
|
2013-02-07 04:58:41 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-06 16:36:05 +00:00
|
|
|
function events() {
|
|
|
|
|
$('#session-contents').on("click", '[action="delete"]', deleteSession);
|
2013-01-31 16:32:32 +00:00
|
|
|
$('#tracks').on('click', 'div[control="mute"]', toggleMute);
|
2013-03-15 02:44:51 +00:00
|
|
|
|
2013-02-03 00:16:12 +00:00
|
|
|
$('#tracks').on('click', 'div[control="fader"]', faderClick);
|
2013-02-03 17:50:26 +00:00
|
|
|
$('#tracks').on('mousedown', 'div[control="fader-handle"]', faderHandleDown);
|
2013-03-15 02:44:51 +00:00
|
|
|
$('#tracks').on('mousemove', faderMouseMove);
|
|
|
|
|
$('body').on('mouseup', faderMouseUp);
|
2013-02-07 04:58:41 +00:00
|
|
|
|
2013-03-14 03:29:57 +00:00
|
|
|
$('#volume').on('click', 'div[control="fader"]', faderClick);
|
2013-03-15 02:44:51 +00:00
|
|
|
$('#volume').on('mousedown', '.slider-volume', faderHandleDown);
|
|
|
|
|
$('body').on('mousemove', faderMouseMove);
|
|
|
|
|
$('body').on('mouseup', faderMouseUp);
|
2013-02-08 05:08:05 +00:00
|
|
|
|
|
|
|
|
// Go ahead and wire up voice-chat events, although it won't be visible
|
|
|
|
|
// (and can't fire events) unless the user has a voice chat mixer
|
2013-03-14 03:29:57 +00:00
|
|
|
$('#voice-chat').on('click', 'div[control="fader"]', faderClick);
|
2013-03-15 02:44:51 +00:00
|
|
|
$('#voice-chat').on('mousedown', 'div[control="fader-handle"]', faderHandleDown);
|
|
|
|
|
$('#voice-chat').on('mousemove', faderMouseMove);
|
|
|
|
|
$('body').on('mouseup', faderMouseUp);
|
2012-10-06 16:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-14 15:48:56 +00:00
|
|
|
this.initialize = function() {
|
2013-02-15 05:15:36 +00:00
|
|
|
context.jamClient.SetVURefreshRate(150);
|
2012-10-14 15:48:56 +00:00
|
|
|
events();
|
2012-12-07 00:28:48 +00:00
|
|
|
var screenBindings = {
|
2012-10-29 15:10:02 +00:00
|
|
|
'beforeShow': beforeShow,
|
2012-10-29 00:37:59 +00:00
|
|
|
'afterShow': afterShow,
|
2012-10-29 15:10:02 +00:00
|
|
|
'beforeHide': beforeHide
|
2012-10-14 15:48:56 +00:00
|
|
|
};
|
|
|
|
|
app.bindScreen('session', screenBindings);
|
2012-10-06 16:36:05 +00:00
|
|
|
};
|
|
|
|
|
|
2012-10-22 02:55:05 +00:00
|
|
|
this.tracks = tracks;
|
|
|
|
|
|
2013-01-30 16:50:43 +00:00
|
|
|
context.JK.HandleBridgeCallback = handleBridgeCallback;
|
|
|
|
|
|
2012-10-06 16:36:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
})(window,jQuery);
|