jam-cloud/app/assets/javascripts/session.js

772 lines
32 KiB
JavaScript
Raw Normal View History

(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.SessionScreen = function(app) {
var logger = context.JK.logger;
var sessionModel = null;
var sessionId;
var tracks = {};
2013-05-15 05:59:09 +00:00
var myTracks = [];
2013-01-30 16:50:43 +00:00
var mixers = [];
var configureTrackDialog;
var addTrackDialog;
var addNewGearDialog;
2013-05-13 22:35:14 +00:00
2013-05-31 02:07:33 +00:00
var screenActive = false;
2013-02-26 03:54:09 +00:00
// TODO Consolidate dragged controls and handles
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;
var $draggingChatHandle = null;
var $draggingChat = null;
var currentMixerIds = null;
var currentMixerRangeMin = null;
var currentMixerRangeMax = null;
var lookingForMixersCount = 0;
var lookingForMixersTimer = null;
var lookingForMixers = {};
var defaultParticipant = {
tracks: [{
instrument_id: "unknown"
}],
user: {
first_name: 'Unknown',
last_name: 'User',
photo_url: null
}
};
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
};
// recreate eThresholdType enum from MixerDialog.h
var alert_type = {
0: { "title": "", "message": "" }, // packet jitter
1: { "title": "Packet Loss", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click here." }, // packet loss
2: { "title": "", "message": "" }, // packet late
3: { "title": "", "message": "" }, // network jitter
2013-07-09 22:46:51 +00:00
4: { "title": "Session Latency", "message": "The latency of your audio device combined with your Internet connection has become high enough to impact your session quality. For troubleshooting tips, click here." }, // network ping
5: { "title": "", "message": "" }, // bitrate throttle warning
6: { "title": "Low Bandwidth", "message": "The available bandwidth on your network has become too low,and this may impact your audio quality. For troubleshooting tips, click here." }, // bandwidth low
7: { "title": "Input Rate", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here." }, // input IO rate
8: { "title": "", "message": "" }, // input IO jitter
9: { "title": "Output Rate", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here." }, // output IO rate
10: { "title": "", "message": "" }, // output IO jitter
2013-07-09 22:46:51 +00:00
11: { "title": "CPU Utilization High", "message": "The CPU of your computer is unable to keep up with the current processing load, and this may impact your audio quality. For troubleshooting tips, click here." }, // CPU load
12: { "title": "", "message": "" }, // decode violations
13: { "title": "", "message": "" }, // last threshold
};
function beforeShow(data) {
sessionId = data.id;
$('#session-mytracks-container').empty();
}
function alertCallback() {
var type = arguments[0];
app.notify({
"title": alert_type[type].title,
"text": alert_type[type].message,
"icon_url": "/assets/content/icon_alert_big.png"
});
}
function afterShow(data) {
2013-05-31 02:07:33 +00:00
// indicate that the screen is active, so that
// body-scoped drag handlers can go active
screenActive = true;
2013-01-30 16:50:43 +00:00
// Subscribe for callbacks on audio events
context.jamClient.SessionRegisterCallback("JK.HandleBridgeCallback");
context.jamClient.SessionSetAlertCallback("JK.AlertCallback");
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() {
sessionModel = new context.JK.SessionModel(
context.JK.JamServer,
context.jamClient,
context.JK.userMe
);
sessionModel.subscribe('sessionScreen', sessionChanged);
sessionModel.joinSession(sessionId);
}
function beforeHide(data) {
2013-05-31 02:07:33 +00:00
// track that the screen is inactive, to disable body-level handlers
screenActive = false;
sessionModel.leaveCurrentSession(sessionId);
// 'unregister' for callbacks
context.jamClient.SessionRegisterCallback("");
context.jamClient.SessionSetAlertCallback("");
}
function sessionChanged() {
logger.info("Session Changed!");
renderSession();
}
function renderSession() {
$('#session-mytracks-container').empty();
$('.session-track').remove(); // Remove previous tracks
2013-01-30 16:50:43 +00:00
_updateMixers();
_renderTracks();
2013-02-07 04:58:41 +00:00
_wireTopVolume();
2013-04-10 15:01:29 +00:00
_wireTopMix();
2013-02-07 04:58:41 +00:00
_addVoiceChat();
_initDialogs();
if ($('.session-livetracks .track').length === 0) {
$('.session-livetracks .when-empty').show();
}
}
2013-05-12 05:43:36 +00:00
function _initDialogs() {
configureTrackDialog.initialize();
addTrackDialog.initialize();
addNewGearDialog.initialize();
2013-01-30 16:50:43 +00:00
}
// Get the latest list of underlying audio mixer channels
function _updateMixers() {
var mixerIds = context.jamClient.SessionGetIDs();
var holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(mixerIds)});
mixers = holder.mixers;
2013-04-10 15:01:29 +00:00
// Always add a hard-coded simplified 'mixer' for the L2M mix
var l2m_mixer = {
id: '__L2M__',
range_low: -80,
range_high: 20,
volume_left: context.jamClient.SessionGetMasterLocalMix()
};
mixers.push(l2m_mixer);
}
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;
}
}
}
});
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);
var gainPercent = percentFromMixerValue(
mixer.range_low, mixer.range_high, mixer.volume_left);
$volumeSlider.find('.handle').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
}
2013-04-10 15:01:29 +00:00
/**
* This control has it's own Set/Get methods, so we don't need to
* line it up with some mixer later. We'll use a special mixer-id value
* to let us know we're dealing with the mix control.
*/
function _wireTopMix() {
var $mixSlider = $('#l2m');
var l2m_mixer = {
range_low: -80,
range_high: 20,
volume_left: context.jamClient.SessionGetMasterLocalMix()
};
var gainPercent = percentFromMixerValue(
l2m_mixer.range_low, l2m_mixer.range_high, l2m_mixer.volume_left);
$mixSlider.find('.handle').css('left', gainPercent + '%');
}
2013-02-07 04:58:41 +00:00
function _addVoiceChat() {
// 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) {
var $voiceChat = $('#voice-chat');
$voiceChat.show();
$voiceChat.attr('mixer-id', mixer.id);
$('#voice-chat .voicechat-mute').attr('mixer-id', mixer.id);
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-07 04:58:41 +00:00
}
function _renderTracks() {
2013-05-15 05:59:09 +00:00
myTracks = [];
// 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;
$.each(sessionModel.participants(), function(index, participant) {
var name = participant.user.name;
if (!(name)) {
name = participant.user.first_name + ' ' + participant.user.last_name;
}
2013-05-15 05:59:09 +00:00
// loop through all tracks for each participant
$.each(participant.tracks, function(index, track) {
var instrumentIcon = context.JK.getInstrumentIcon45(track.instrument_id);
var photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
var myTrack = false;
// Default trackData to participant + no Mixer state.
var trackData = {
trackId: track.id,
2013-05-22 11:48:37 +00:00
connection_id: track.connection_id,
2013-05-15 05:59:09 +00:00
clientId: participant.client_id,
name: name,
instrumentIcon: instrumentIcon,
avatar: photoUrl,
latency: "good",
gainPercent: 0,
muteClass: 'muted',
mixerId: ""
};
var mixer = _mixerForClientId(
participant.client_id,
[
ChannelGroupIds.AudioInputMusicGroup,
ChannelGroupIds.UserMusicInputGroup
]);
if (mixer) {
myTrack = (mixer.group_id === ChannelGroupIds.AudioInputMusicGroup);
var gainPercent = percentFromMixerValue(
mixer.range_low, mixer.range_high, mixer.volume_left);
var muteClass = "enabled";
if (mixer.mute) {
muteClass = "muted";
}
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);
}
}
_addTrack(index, trackData);
2013-05-15 05:59:09 +00:00
// Show settings icons only for my tracks
if (myTrack) {
$('div[mixer-id="' + mixer.id + '"].track-icon-settings').show();
2013-05-24 01:16:00 +00:00
myTracks.push(trackData);
}
2013-05-24 01:16:00 +00:00
// TODO: UNCOMMENT THIS WHEN TESTING LOCALLY IN BROWSER
//myTracks.push(trackData);
2013-05-15 05:59:09 +00:00
});
});
configureTrackDialog = new context.JK.ConfigureTrackDialog(app, myTracks, sessionId, sessionModel);
addTrackDialog = new context.JK.AddTrackDialog(app, myTracks, sessionId, sessionModel);
addNewGearDialog = new context.JK.AddNewGearDialog(app);
2013-05-12 05:43:36 +00:00
// hide "Add Track" link if there are 2 tracks
if (myTracks.length === 2) {
$('#div-add-track').hide();
2013-05-12 05:43:36 +00:00
}
else {
$('#div-add-track').show();
$('#div-add-track').click(function() {
addTrackDialog.showDialog();
});
2013-05-12 05:43:36 +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
]);
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
$track.find('.track-vu-left').attr('mixer-id', mixer.id + "_vul");
$track.find('.track-vu-right').attr('mixer-id', mixer.id + "_vur");
$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) {
// 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
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';
}
selector = '#tracks table[mixer-id="' + mixerId + '"] td.vu' + i;
2013-01-30 16:50:43 +00:00
$light = $(selector);
$light.addClass(colorClass + state);
}
}
function _addTrack(index, trackData) {
var $destination = $('#session-mytracks-container');
if (trackData.clientId !== app.clientId) {
$destination = $('#session-livetracks-container');
$('.session-livetracks .when-empty').hide();
}
trackData["left-vu"] = $('#template-vu').html();
trackData["right-vu"] = trackData["left-vu"];
var template = $('#template-session-track').html();
var newTrack = context.JK.fillTemplate(template, trackData);
$destination.append(newTrack);
var $closeButton = $('#div-track-close', 'div[track-id="' + trackData.trackId + '"]');
if (index === 0) {
$closeButton.hide();
}
else {
$closeButton.click(deleteTrack);
}
2013-05-12 05:43:36 +00:00
$('div[mixer-id="' + trackData.mixerId + '"].track-icon-settings').click(function() {
2013-05-16 05:15:16 +00:00
// call this to initialize Voice Chat tab
configureTrackDialog.showVoiceChatPanel(true);
configureTrackDialog.showMusicAudioPanel(true);
2013-05-12 05:43:36 +00:00
});
2013-05-15 05:59:09 +00:00
tracks[trackData.trackId] = new context.JK.SessionTrack(trackData.clientId);
}
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') {
mixerId = mixerId + "_vul";
} else {
mixerId = mixerId + "_vur";
}
_updateVU(mixerId, vuVal);
} 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.
} else {
// Examples of other events
// Add media file track: "add", "The_Abyss_4T", 0
logger.debug('non-vu event: ' + eventName + ',' + mixerId + ',' + value);
}
2013-01-30 16:50:43 +00:00
}
}
function deleteSession(evt) {
var sessionId = $(evt.currentTarget).attr("action-id");
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);
}
});
}
}
function deleteTrack(evt) {
var trackId = $(evt.currentTarget).attr("track-id");
sessionModel.deleteTrack(sessionId, trackId);
}
function _toggleVisualMuteControl($control, muting) {
if (muting) {
$control.removeClass('enabled');
$control.addClass('muted');
} else {
$control.removeClass('muted');
$control.addClass('enabled');
}
}
function _toggleAudioMute(mixerId, muting) {
fillTrackVolumeObject(mixerId);
context.trackVolumeObject.mute = muting;
context.jamClient.SessionSetControlState(mixerId);
}
function toggleMute(evt) {
var $control = $(evt.currentTarget);
var muting = ($control.hasClass('enabled'));
var mixerIds = $control.attr('mixer-id').split(',');
$.each(mixerIds, function(i,v) {
_toggleAudioMute(v, muting);
});
_toggleVisualMuteControl($control, muting);
}
function getVerticalFaderPercent(eventY, $fader) {
return getFaderPercent(eventY, $fader, 'vertical');
}
2013-02-07 04:58:41 +00:00
function getHorizontalFaderPercent(eventX, $fader) {
return getFaderPercent(eventX, $fader, 'horizontal');
}
function getFaderPercent(value, $fader, orientation) {
2013-02-07 04:58:41 +00:00
var faderPosition = $fader.offset();
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;
}
function fillTrackVolumeObject(mixerId, broadcast) {
_updateMixers();
var mixer = null;
var _broadcast = true;
if (broadcast !== undefined) {
_broadcast = broadcast;
}
for (var i=0; i<mixers.length; i++) {
mixer = mixers[i];
if (mixer.id === mixerId) {
context.trackVolumeObject.clientID = mixer.client_id;
context.trackVolumeObject.broadcast = _broadcast;
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;
}
}
}
// 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;
}
// Given a volume percent (0-100), set the underlying
// audio volume level of the passed mixerId to the correct
// value.
function setMixerVolume(mixerId, volumePercent) {
// 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.
var sliderValue = percentToMixerValue(
currentMixerRangeMin, currentMixerRangeMax, volumePercent);
context.trackVolumeObject.volL = sliderValue;
context.trackVolumeObject.volR = sliderValue;
2013-04-10 15:01:29 +00:00
// Special case for L2M mix:
if (mixerId === '__L2M__') {
context.jamClient.SessionSetMasterLocalMix(sliderValue);
} else {
context.jamClient.SessionSetControlState(mixerId);
}
}
// Refactor. Only need one of these xxxDown methods.
2013-02-03 17:50:26 +00:00
function faderHandleDown(evt) {
2013-05-31 02:07:33 +00:00
if (!screenActive) return true; // allow other screens to use mouseevents while this screen is not active
2013-02-03 17:50:26 +00:00
evt.stopPropagation();
$draggingFaderHandle = $(evt.currentTarget);
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
currentMixerIds = $draggingFader.closest('[mixer-id]').attr('mixer-id').split(',');
var mixerIds = currentMixerIds;
$.each(mixerIds, function(i,v) {
fillTrackVolumeObject(v);
});
return false;
}
function faderMouseUp(evt) {
2013-05-31 02:07:33 +00:00
if (!screenActive) return true; // allow other screens to use mouseevents while this screen is not active
evt.stopPropagation();
if ($draggingFaderHandle) {
$draggingFaderHandle = null;
2013-02-03 17:50:26 +00:00
$draggingFader = null;
currentMixerIds = null;
}
return false;
}
function faderMouseMove(evt) {
2013-05-31 02:07:33 +00:00
if (!screenActive) return true; // allow other screens to use mouseevents while this screen is not active
// bail out early if there's no in-process drag
if (!($draggingFaderHandle)) {
return false;
2013-02-03 17:50:26 +00:00
}
var $fader = $draggingFader;
var $handle = $draggingFaderHandle;
evt.stopPropagation();
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';
}
var faderPct = getPercentFunction(absolutePosition, $fader);
var mixerIds = currentMixerIds;
$.each(mixerIds, function(i,v) {
setMixerVolume(v, faderPct);
});
if (faderPct > 90) { faderPct = 90; } // Visual limit
$handle.css(handleCssAttribute, faderPct + '%');
2013-02-07 04:58:41 +00:00
return false;
}
function faderClick(evt) {
2013-02-07 04:58:41 +00:00
evt.stopPropagation();
if ($draggingFaderHandle) {
return;
2013-02-07 04:58:41 +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-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;
}
function events() {
$('#session-contents').on("click", '[action="delete"]', deleteSession);
$('#tracks').on('click', 'div[control="mute"]', toggleMute);
$('#tracks').on('click', 'div[control="fader"]', faderClick);
2013-02-03 17:50:26 +00:00
$('#tracks').on('mousedown', 'div[control="fader-handle"]', faderHandleDown);
$('#tracks').on('mousemove', faderMouseMove);
$('body').on('mouseup', faderMouseUp);
2013-02-07 04:58:41 +00:00
$('#session-controls .fader').on('click', 'div[control="fader"]', faderClick);
$('#session-controls .fader').on('mousedown', '.handle', faderHandleDown);
$('body').on('mousemove', faderMouseMove);
$('body').on('mouseup', faderMouseUp);
// 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);
$('#voice-chat').on('mousedown', 'div[control="fader-handle"]', faderHandleDown);
$('#voice-chat').on('mousemove', faderMouseMove);
$('body').on('mouseup', faderMouseUp);
2013-05-12 05:43:36 +00:00
$('.voicechat-settings').click(function() {
2013-05-16 05:15:16 +00:00
// call this to initialize Music Audio tab
configureTrackDialog.showMusicAudioPanel(true);
configureTrackDialog.showVoiceChatPanel(true);
2013-05-18 05:59:25 +00:00
});
}
this.initialize = function() {
context.jamClient.SetVURefreshRate(150);
events();
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow,
'beforeHide': beforeHide
};
app.bindScreen('session', screenBindings);
};
this.tracks = tracks;
this.getCurrentSession = function() {
return sessionModel.getCurrentSession();
};
this.refreshCurrentSession = function() {
sessionModel.refreshCurrentSession();
};
2013-01-30 16:50:43 +00:00
context.JK.HandleBridgeCallback = handleBridgeCallback;
context.JK.AlertCallback = alertCallback;
2013-01-30 16:50:43 +00:00
};
})(window,jQuery);