* VRFS-1491 - finishing up dealing with refactor of monitor vs master tracks
This commit is contained in:
parent
76adc44a50
commit
eedc5ae970
|
|
@ -228,4 +228,5 @@ user_syncs_fix_dup_tracks_2408.sql
|
|||
deletable_recordings.sql
|
||||
jam_tracks.sql
|
||||
shopping_carts.sql
|
||||
recurly.sql
|
||||
recurly.sql
|
||||
add_track_resource_id.sql
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE tracks ADD COLUMN client_resource_id VARCHAR(100);
|
||||
|
|
@ -188,6 +188,7 @@ module JamRuby
|
|||
t.connection = self
|
||||
t.sound = track["sound"]
|
||||
t.client_track_id = track["client_track_id"]
|
||||
t.client_resource_id = track["client_resource_id"]
|
||||
t.save # todo what if it fails?
|
||||
self.tracks << t
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ module JamRuby
|
|||
|
||||
validates :sound, :inclusion => {:in => SOUND}
|
||||
validates :connection, presence: true
|
||||
validates :client_track_id, presence: true
|
||||
#validates :client_resource_id, presence: true
|
||||
|
||||
def user
|
||||
self.connection.user
|
||||
|
|
@ -89,6 +91,7 @@ module JamRuby
|
|||
connection_track.instrument_id = track[:instrument_id]
|
||||
connection_track.sound = track[:sound]
|
||||
connection_track.client_track_id = track[:client_track_id]
|
||||
connection_track.client_resource_id = track[:client_resource_id]
|
||||
|
||||
result.push(connection_track)
|
||||
|
||||
|
|
@ -114,6 +117,7 @@ module JamRuby
|
|||
connection_track.instrument_id = track[:instrument_id]
|
||||
connection_track.sound = track[:sound]
|
||||
connection_track.client_track_id = track[:client_track_id]
|
||||
connection_track.client_resource_id = track[:client_resource_id]
|
||||
if connection_track.save
|
||||
result.push(connection_track)
|
||||
else
|
||||
|
|
@ -131,7 +135,7 @@ module JamRuby
|
|||
result
|
||||
end
|
||||
|
||||
def self.save(id, connection_id, instrument_id, sound, client_track_id)
|
||||
def self.save(id, connection_id, instrument_id, sound, client_track_id, client_resource_id)
|
||||
if id.nil?
|
||||
track = Track.new
|
||||
track.connection_id = connection_id
|
||||
|
|
@ -151,6 +155,10 @@ module JamRuby
|
|||
track.client_track_id = client_track_id
|
||||
end
|
||||
|
||||
unless client_resource_id.nil?
|
||||
track.client_resource_id = resource_id
|
||||
end
|
||||
|
||||
track.updated_at = Time.now
|
||||
track.save
|
||||
return track
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ FactoryGirl.define do
|
|||
factory :track, :class => JamRuby::Track do
|
||||
sound "mono"
|
||||
sequence(:client_track_id) { |n| "client_track_id#{n}"}
|
||||
sequence(:client_resource_id) { |n| "resource_id#{n}"}
|
||||
end
|
||||
|
||||
factory :video_source, :class => JamRuby::VideoSource do
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ describe Track do
|
|||
track.id.should_not be_nil
|
||||
connection.tracks.length.should == 1
|
||||
set_updated_at(track, 1.days.ago)
|
||||
tracks = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id}])
|
||||
tracks = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id, client_resource_id: track.client_resource_id}])
|
||||
tracks.length.should == 1
|
||||
found = tracks[0]
|
||||
expect(found.id).to eq track.id
|
||||
|
|
|
|||
|
|
@ -16,9 +16,18 @@
|
|||
var logger = g.JK.logger;
|
||||
|
||||
function faderClick(e) {
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
var $fader = $(this);
|
||||
|
||||
var recordingDisabled = $fader.data('recording-disabled');
|
||||
if(recordingDisabled) {
|
||||
var recordingOpener = $fader.data('recording-opener');
|
||||
window.JK.prodBubble($fader, 'recording-controls-disabled', {recordingOpener:recordingOpener}, {positions:['top'], offsetParent: $fader.closest('.screen')})
|
||||
return false;
|
||||
}
|
||||
|
||||
draggingOrientation = $fader.attr('orientation');
|
||||
var offset = $fader.offset();
|
||||
var position = { top: e.pageY - offset.top, left: e.pageX - offset.left}
|
||||
|
|
@ -117,6 +126,14 @@
|
|||
$draggingFaderHandle = $(this);
|
||||
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
|
||||
draggingOrientation = $draggingFader.attr('orientation');
|
||||
|
||||
var recordingDisabled = $draggingFaderHandle.data('recording-disabled');
|
||||
var recordingOpener = $draggingFaderHandle.data('recording-opener');
|
||||
|
||||
if(recordingDisabled) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function onFaderDragStop(e, ui) {
|
||||
|
|
@ -162,13 +179,15 @@
|
|||
|
||||
selector.html(g._.template(templateSource, options));
|
||||
|
||||
selector.find('div[control="fader"]').data('recording-disabled', selector.data('recording-disabled')).data('recording-opener', selector.data('recording-opener'))
|
||||
|
||||
selector.find('div[control="fader-handle"]').draggable({
|
||||
drag: onFaderDrag,
|
||||
start: onFaderDragStart,
|
||||
stop: onFaderDragStop,
|
||||
containment: "parent",
|
||||
axis: options.faderType === 'horizontal' ? 'x' : 'y'
|
||||
})
|
||||
}).data('recording-disabled', selector.data('recording-disabled')).data('recording-opener', selector.data('recording-opener'))
|
||||
|
||||
// Embed any custom styles, applied to the .fader below selector
|
||||
if ("style" in options) {
|
||||
|
|
|
|||
|
|
@ -392,6 +392,10 @@
|
|||
logger.debug("Fake JamClient: SessionAudioResync()");
|
||||
}
|
||||
|
||||
function SessionGetAllControlState(isMasterOrPersonal) {
|
||||
var mixerIds = SessionGetIDs()
|
||||
return SessionGetControlState(mixerIds, isMasterOrPersonal);
|
||||
}
|
||||
function SessionGetControlState(mixerIds, isMasterOrPersonal) {
|
||||
dbg("SessionGetControlState");
|
||||
var groups = [0, 1, 2, 3, 7, 9];
|
||||
|
|
@ -416,9 +420,9 @@
|
|||
response.push({
|
||||
client_id: clientIds[i],
|
||||
group_id: groups[i],
|
||||
id: mixerIds[i],
|
||||
master: true,
|
||||
monitor: true,
|
||||
id: mixerIds[i] + (isMasterOrPersonal ? 'm' : 'p'),
|
||||
master: isMasterOrPersonal,
|
||||
monitor: !isMasterOrPersonal,
|
||||
mute: false,
|
||||
name: names[i],
|
||||
range_high: 20,
|
||||
|
|
@ -428,7 +432,8 @@
|
|||
volume_left: -40,
|
||||
volume_right:-40,
|
||||
instrument_id:50, // see globals.js
|
||||
mode: false
|
||||
mode: isMasterOrPersonal,
|
||||
rid: mixerIds[i]
|
||||
});
|
||||
}
|
||||
return response;
|
||||
|
|
@ -504,7 +509,7 @@
|
|||
}
|
||||
|
||||
function doCallbacks() {
|
||||
var names = ["left_vu", "right_vu"];
|
||||
var names = ["vu"];
|
||||
//var ids = ["FW AP Multi_2_10200", "FW AP Multi_0_10000"];
|
||||
var ids= ["i~11~MultiChannel (FW AP Multi)~0^i~11~Multichannel (FW AP Multi)~1",
|
||||
"i~11~MultiChannel (FW AP Multi)~0^i~11~Multichannel (FW AP Multi)~2"];
|
||||
|
|
@ -518,7 +523,7 @@
|
|||
}
|
||||
}
|
||||
var js = eventCallbackName + '(' + args.join(',') + ')';
|
||||
eval(js);
|
||||
//eval(js);
|
||||
|
||||
vuValue += vuChange;
|
||||
if (vuValue > 10 || vuValue < -70) { vuChange = vuChange * -1; }
|
||||
|
|
@ -912,6 +917,8 @@
|
|||
// Session
|
||||
this.SessionAddTrack = SessionAddTrack;
|
||||
this.SessionGetControlState = SessionGetControlState;
|
||||
this.SessionGetAllControlState = SessionGetAllControlState;
|
||||
this.SessionSetUserName = SessionSetUserName;
|
||||
this.SessionGetIDs = SessionGetIDs;
|
||||
this.RegisterRecordingManagerCallbacks = RegisterRecordingManagerCallbacks;
|
||||
this.RegisterRecordingCallbacks = RegisterRecordingCallbacks;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
var myTracks = [];
|
||||
var masterMixers = [];
|
||||
var personalMixers = [];
|
||||
var allMixers = {};
|
||||
var mixersByResourceId = {};
|
||||
var mixersByTrackId = {};
|
||||
var configureTrackDialog;
|
||||
var addNewGearDialog;
|
||||
var localRecordingsDialog = null;
|
||||
|
|
@ -29,7 +32,7 @@
|
|||
var currentMixerRangeMax = null;
|
||||
var lookingForMixersCount = 0;
|
||||
var lookingForMixersTimer = null;
|
||||
var lookingForMixers = {};
|
||||
var lookingForMixers = [];
|
||||
var $recordingTimer = null;
|
||||
var recordingTimerInterval = null;
|
||||
var startTimeDate = null;
|
||||
|
|
@ -454,15 +457,44 @@
|
|||
* you must iterate. Convenience method to locate a particular
|
||||
* mixer by id.
|
||||
*/
|
||||
function getMixer(mixerId, mixMode) {
|
||||
var foundMixer = null;
|
||||
var mixers = mixMode == MIX_MODES.MASTER ? masterMixers : personalMixers;
|
||||
$.each(mixers, function(index, mixer) {
|
||||
if (mixer.id === mixerId) {
|
||||
foundMixer = mixer;
|
||||
}
|
||||
});
|
||||
return foundMixer;
|
||||
function getMixer(mixerId) {
|
||||
return allMixers[mixerId];
|
||||
}
|
||||
|
||||
function getMixerByResourceId(resourceId, mode) {
|
||||
var mixerPair = mixersByResourceId[resourceId];
|
||||
|
||||
if(!mixerPair) {return null;}
|
||||
|
||||
if(mode === undefined) {
|
||||
return mixerPair;
|
||||
}
|
||||
else {
|
||||
if(mode == MIX_MODES.MASTER) {
|
||||
return mixerPair.master;
|
||||
}
|
||||
else {
|
||||
return mixerPair.personal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMixerByTrackId(trackId, mode) {
|
||||
var mixerPair = mixersByTrackId[trackId];
|
||||
|
||||
if(!mixerPair) {return null;}
|
||||
|
||||
if(mode === undefined) {
|
||||
return mixerPair;
|
||||
}
|
||||
else {
|
||||
if(mode == MIX_MODES.MASTER) {
|
||||
return mixerPair.master;
|
||||
}
|
||||
else {
|
||||
return mixerPair.personal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderSession() {
|
||||
|
|
@ -492,19 +524,58 @@
|
|||
addNewGearDialog.initialize();
|
||||
}
|
||||
|
||||
// Get the latest list of underlying audio mixer channels
|
||||
// Get the latest list of underlying audio mixer channels, and populates:
|
||||
// * mixersByResourceId - a hash of resourceId / { master: mixer, personal: mixer } personal: can be null in case of PeerAudioInputMusicGroup
|
||||
// * mixersByTrackId - a hash of track id / {master: mixer, personal: mixer}.
|
||||
// * allMixers - a hash of mixer.id / mixer
|
||||
// * masterMixers - array of master mode mixers
|
||||
// * personalMixers - array of personal mode mixers
|
||||
function _updateMixers() {
|
||||
|
||||
masterMixers = context.jamClient.SessionGetAllControlState(true);
|
||||
//var holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(masterMixerIds, true)});
|
||||
//masterMixers = masterMixerIds.mixers;
|
||||
|
||||
personalMixers = context.jamClient.SessionGetAllControlState(false);
|
||||
//holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(personalMixerIds, false)});
|
||||
//personalMixers = personalMixerIds.mixers;
|
||||
|
||||
console.log("masterMixers", masterMixers)
|
||||
console.log("personalMixers", personalMixers)
|
||||
//logger.debug("masterMixers", masterMixers)
|
||||
//logger.debug("personalMixers", personalMixers)
|
||||
|
||||
mixersByResourceId = {}
|
||||
mixersByTrackId = {}
|
||||
allMixers = {}
|
||||
|
||||
var i;
|
||||
for(i = 0; i < masterMixers.length; i++) {
|
||||
var masterMixer = masterMixers[i];
|
||||
allMixers[masterMixer.id] = masterMixer; // populate allMixers by mixer.id
|
||||
|
||||
// populate mixer pair
|
||||
var mixerPair = {}
|
||||
mixersByResourceId[masterMixer.rid] = mixerPair
|
||||
mixersByTrackId[masterMixer.id] = mixerPair
|
||||
mixerPair.master = masterMixer;
|
||||
}
|
||||
for(i = 0; i < personalMixers.length; i++) {
|
||||
var personalMixer = personalMixers[i];
|
||||
|
||||
if(personalMixer.group_id == ChannelGroupIds.MediaTrackGroup) {
|
||||
continue;
|
||||
}
|
||||
|
||||
allMixers[personalMixer.id] = personalMixer
|
||||
|
||||
// populate other side of mixer pair
|
||||
|
||||
var mixerPair = mixersByResourceId[personalMixer.rid]
|
||||
if(!mixerPair) {
|
||||
if(personalMixer.group_id != ChannelGroupIds.MonitorGroup) {
|
||||
logger.warn("there is no master version of ", personalMixer)
|
||||
}
|
||||
|
||||
mixerPair = {}
|
||||
mixersByResourceId[personalMixer.rid] = mixerPair
|
||||
}
|
||||
mixersByTrackId[personalMixer.id] = mixerPair;
|
||||
|
||||
mixerPair.personal = personalMixer;
|
||||
}
|
||||
// Always add a hard-coded simplified 'mixer' for the L2M mix
|
||||
|
||||
/**
|
||||
|
|
@ -565,7 +636,7 @@
|
|||
//logger.debug("clientId", clientId, "groupIds", groupIds, "mixers", mixers)
|
||||
var foundMixers = {};
|
||||
var mixers = mixMode == MIX_MODES.MASTER ? masterMixers : personalMixers;
|
||||
console.log("_groupedMixersForClientId", mixers)
|
||||
// console.log("_groupedMixersForClientId", mixers)
|
||||
$.each(mixers, function(index, mixer) {
|
||||
if (mixer.client_id === clientId) {
|
||||
for (var i=0; i<groupIds.length; i++) {
|
||||
|
|
@ -694,16 +765,20 @@
|
|||
$voiceChatGain.on('fader_change', faderChanged);
|
||||
context.JK.FaderHelpers.setFaderValue(mixer.id, gainPercent);
|
||||
//if (mixer.mute) {
|
||||
_toggleVisualMuteControl($voiceChatMute, mixer, null);
|
||||
_toggleVisualMuteControl($voiceChatMute, mixer.mute);
|
||||
//}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _renderLocalMediaTracks() {
|
||||
var localMediaMixers = _mixersForGroupId(ChannelGroupIds.MediaTrackGroup, sessionModel.getMixMode());
|
||||
|
||||
// is this the person who opened the recording?
|
||||
var isOpener = true;
|
||||
var localMediaMixers = _mixersForGroupId(ChannelGroupIds.MediaTrackGroup, MIX_MODES.MASTER);
|
||||
if(localMediaMixers.length == 0) {
|
||||
localMediaMixers = _mixersForGroupId(ChannelGroupIds.PeerMediaTrackGroup, sessionModel.getMixMode());
|
||||
isOpener = false; // if we have PeerMediaTracks, then we didn't open the recording
|
||||
localMediaMixers = _mixersForGroupId(ChannelGroupIds.PeerMediaTrackGroup, MIX_MODES.MASTER);
|
||||
}
|
||||
|
||||
var recordedTracks = sessionModel.recordedTracks();
|
||||
|
|
@ -791,7 +866,13 @@
|
|||
trackData.gainPercent = gainPercent;
|
||||
trackData.muteClass = muteClass;
|
||||
trackData.mixerId = mixer.id;
|
||||
trackData.vuMixerId = mixer.id;
|
||||
trackData.muteMixerId = mixer.id;
|
||||
|
||||
if(sessionModel.isPersonalMixMode() || !isOpener) {
|
||||
trackData.recordingDisabled = true;
|
||||
trackData.recordingOpener = isOpener;
|
||||
}
|
||||
_addMediaTrack(trackData);
|
||||
});
|
||||
|
||||
|
|
@ -817,16 +898,108 @@
|
|||
var mixer = $muteControl.data('mixer')
|
||||
var oppositeMixer = $muteControl.data('opposite-mixer')
|
||||
|
||||
if(mixer.group_id == ChannelGroupIds.AudioInputMusicGroup || mixer.group_id == ChannelGroupIds.MediaTrackGroup) {
|
||||
context.jamClient.SessionSetControlState(mixer.id, sessionModel.isMasterMixMode());
|
||||
context.jamClient.SessionSetControlState(mixer.id, !sessionModel.isMasterMixMode());
|
||||
|
||||
logger.debug("muting tracks. current mixer id=" + mixer.id + ", opposite mixer id=" + oppositeMixer.id)
|
||||
|
||||
var mixerPair = {}
|
||||
if(sessionModel.isMasterMixMode()) {
|
||||
mixerPair.master = mixer;
|
||||
mixerPair.personal = oppositeMixer;
|
||||
}
|
||||
else if(mixer.group_id == ChannelGroupIds.UserMusicInputGroup || mixer.group_id == ChannelGroupIds.PeerAudioInputMusicGroup) {
|
||||
context.jamClient.SessionSetControlState(mixer.id, sessionModel.isMasterMixMode());
|
||||
context.jamClient.SessionSetControlState(oppositeMixer.id, !sessionModel.isMasterMixMode());
|
||||
else {
|
||||
mixerPair.master = oppositeMixer;
|
||||
mixerPair.personal = mixer;
|
||||
}
|
||||
if(muteOption == 'master') {
|
||||
_toggleAudioMute(mixerPair.master.id, true, mixerPair.master.mode);
|
||||
_toggleAudioMute(mixerPair.personal.id, true, mixerPair.personal.mode);
|
||||
}
|
||||
else {
|
||||
_toggleAudioMute(mixerPair.personal.id, true, mixerPair.personal.mode);
|
||||
_toggleAudioMute(mixerPair.master.id, false, mixerPair.master.mode);
|
||||
}
|
||||
|
||||
_toggleVisualMuteControl($control, true);
|
||||
_toggleVisualMuteControl($muteControl, true);
|
||||
}
|
||||
|
||||
// find backend mixer based on track data, and target client_id
|
||||
function findMixerForTrack(client_id, track, myTrack) {
|
||||
var mixer = null; // what is the best mixer for this track/client ID?
|
||||
var oppositeMixer = null; // what is the corresponding mixer in the opposite mode?
|
||||
var vuMixer = null;
|
||||
var muteMixer = null;
|
||||
|
||||
var mixMode = sessionModel.getMixMode();
|
||||
if(myTrack) {
|
||||
// when it's your track, look it up by the backend resource ID
|
||||
mixer = getMixerByTrackId(track.client_track_id, mixMode)
|
||||
vuMixer = mixer;
|
||||
muteMixer = mixer;
|
||||
|
||||
// sanity checks
|
||||
if(mixer && (mixer.group_id != ChannelGroupIds.AudioInputMusicGroup)) { logger.error("found local mixer that was not of groupID: AudioInputMusicGroup", mixer) }
|
||||
|
||||
if(mixer) {
|
||||
// find the matching AudioInputMusicGroup for the opposite mode
|
||||
oppositeMixer = getMixerByTrackId(track.client_track_id, !mixMode)
|
||||
|
||||
if(mixMode == MIX_MODES.PERSONAL) {
|
||||
muteMixer = oppositeMixer; // make the master mixer the mute mixer
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
if(!oppositeMixer) {logger.error("unable to find opposite mixer for local mixer", mixer)}
|
||||
else if(oppositeMixer.group_id != ChannelGroupIds.AudioInputMusicGroup) { logger.error("found local mixer in opposite mode that was not of groupID: AudioInputMusicGroup", mixer, oppositeMixer)}
|
||||
}
|
||||
else {
|
||||
logger.debug("local track is not present: ", track)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(mixMode === MIX_MODES.MASTER) {
|
||||
|
||||
// when it's a remote track and in master mode, we should find the PeerAudioInputMusicGroup
|
||||
mixer = getMixerByTrackId(track.client_track_id, MIX_MODES.MASTER)
|
||||
if(mixer && (mixer.group_id != ChannelGroupIds.PeerAudioInputMusicGroup)) { logger.error("found remote mixer that was not of groupID: PeerAudioInputMusicGroup", mixer) }
|
||||
|
||||
vuMixer = mixer;
|
||||
muteMixer = mixer;
|
||||
|
||||
if(mixer) {
|
||||
// we should be able to find a UserMusicInputGroup for this clientId in personal mode
|
||||
var oppositeMixers = _groupedMixersForClientId(client_id, [ ChannelGroupIds.UserMusicInputGroup], {}, MIX_MODES.PERSONAL);
|
||||
if (oppositeMixers[ChannelGroupIds.UserMusicInputGroup]) { oppositeMixer = oppositeMixers[ChannelGroupIds.UserMusicInputGroup][0]; }
|
||||
|
||||
if(!oppositeMixer) {logger.error("unable to find UserMusicInputGroup corresponding to PeerAudioInputMusicGroup mixer", mixer ) }
|
||||
}
|
||||
}
|
||||
else {
|
||||
// when it's a remote track and in personal mode, we want the 'Peer Stream', which is UserMusicInputGroup
|
||||
// this spans N tracks for the remote user
|
||||
var mixers = _groupedMixersForClientId(client_id, [ ChannelGroupIds.UserMusicInputGroup], {}, MIX_MODES.PERSONAL);
|
||||
if (mixers[ChannelGroupIds.UserMusicInputGroup]) { mixer = mixers[ChannelGroupIds.UserMusicInputGroup][0]; }
|
||||
|
||||
vuMixer = mixer;
|
||||
muteMixer = mixer;
|
||||
|
||||
if(mixer) {
|
||||
// now grab the PeerAudioInputMusicGroup in master mode to satisfy the 'opposite' mixer
|
||||
oppositeMixer = getMixerByTrackId(track.client_track_id, MIX_MODES.MASTER)
|
||||
if(!oppositeMixer) {logger.debug("unable to find a PeerAudioInputMusicGroup master mixer matching a UserMusicInput", track.client_track_id, mixersByTrackId)}
|
||||
else if(oppositeMixer.group_id != ChannelGroupIds.PeerAudioInputMusicGroup) { logger.error("found remote mixer that was not of groupID: PeerAudioInputMusicGroup", mixer) }
|
||||
|
||||
vuMixer = oppositeMixer; // for personal mode, use the PeerAudioInputMusicGroup's VUs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
mixer: mixer,
|
||||
oppositeMixer: oppositeMixer,
|
||||
vuMixer: vuMixer,
|
||||
muteMixer: muteMixer
|
||||
}
|
||||
}
|
||||
function _renderTracks() {
|
||||
myTracks = [];
|
||||
|
|
@ -834,6 +1007,8 @@
|
|||
// 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.
|
||||
|
||||
lookingForMixers = [] // clear this back out as we are restarting from scratch
|
||||
lookingForMixersCount = 0;
|
||||
$.each(sessionModel.participants(), function(index, participant) {
|
||||
|
||||
|
|
@ -842,19 +1017,19 @@
|
|||
name = participant.user.first_name + ' ' + participant.user.last_name;
|
||||
}
|
||||
|
||||
var usedMixers = {}; // Once we use a mixer, we add it here to allow us to find 'second' tracks
|
||||
var myTrack = app.clientId == participant.client_id;
|
||||
|
||||
// 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,
|
||||
connection_id: track.connection_id,
|
||||
client_track_id: track.client_track_id,
|
||||
client_resource_id: track.client_resource_id,
|
||||
clientId: participant.client_id,
|
||||
name: name,
|
||||
instrumentIcon: instrumentIcon,
|
||||
|
|
@ -867,53 +1042,15 @@
|
|||
preMasteredClass: ""
|
||||
};
|
||||
|
||||
// This is the likely cause of multi-track problems.
|
||||
// This should really become _mixersForClientId and return a list.
|
||||
// With multiple tracks, there will be more than one mixer for a
|
||||
// particular client, in a particular group, and I'll need to further
|
||||
// identify by track id or something similar.
|
||||
var mixerData = findMixerForTrack(participant.client_id, track, myTrack)
|
||||
var mixer = mixerData.mixer;
|
||||
var vuMixer = mixerData.vuMixer;
|
||||
var muteMixer = mixerData.muteMixer;
|
||||
var oppositeMixer = mixerData.oppositeMixer;
|
||||
|
||||
|
||||
var currentMixers = _groupedMixersForClientId(
|
||||
participant.client_id,
|
||||
[
|
||||
ChannelGroupIds.AudioInputMusicGroup,
|
||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
||||
ChannelGroupIds.UserMusicInputGroup
|
||||
],
|
||||
usedMixers, sessionModel.getMixMode());
|
||||
|
||||
var oppositeMixers = _groupedMixersForClientId(
|
||||
participant.client_id,
|
||||
[
|
||||
ChannelGroupIds.AudioInputMusicGroup,
|
||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
||||
ChannelGroupIds.UserMusicInputGroup
|
||||
],
|
||||
usedMixers, !sessionModel.getMixMode());
|
||||
|
||||
console.log("currentMixers", currentMixers)
|
||||
console.log("oppositeMixers", oppositeMixers)
|
||||
|
||||
var mixer = null;
|
||||
var oppositeMixer = null;
|
||||
if(currentMixers) {
|
||||
if(currentMixers[ChannelGroupIds.AudioInputMusicGroup]) {
|
||||
mixer = currentMixers[ChannelGroupIds.AudioInputMusicGroup][0]
|
||||
oppositeMixer = oppositeMixers[ChannelGroupIds.AudioInputMusicGroup][0]
|
||||
}
|
||||
else if(sessionModel.isMasterMixMode() && currentMixers[ChannelGroupIds.PeerAudioInputMusicGroup]) {
|
||||
mixer = currentMixers[ChannelGroupIds.PeerAudioInputMusicGroup][0]
|
||||
oppositeMixer = oppositeMixers[ChannelGroupIds.UserMusicInputGroup][0]
|
||||
}
|
||||
else if(!sessionModel.isMasterMixMode() && currentMixers[ChannelGroupIds.UserMusicInputGroup]) {
|
||||
mixer = currentMixers[ChannelGroupIds.UserMusicInputGroup][0]
|
||||
oppositeMixer = oppositeMixers[ChannelGroupIds.PeerAudioInputMusicGroup][0]
|
||||
}
|
||||
}
|
||||
|
||||
if (mixer) {
|
||||
usedMixers[mixer.id] = true;
|
||||
if (mixer && oppositeMixer) {
|
||||
myTrack = (mixer.group_id === ChannelGroupIds.AudioInputMusicGroup);
|
||||
var gainPercent = percentFromMixerValue(
|
||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||
|
|
@ -925,13 +1062,15 @@
|
|||
trackData.gainPercent = gainPercent;
|
||||
trackData.muteClass = muteClass;
|
||||
trackData.mixerId = mixer.id;
|
||||
trackData.vuMixerId = vuMixer.id;
|
||||
trackData.oppositeMixer = oppositeMixer;
|
||||
trackData.muteMixerId = muteMixer.id;
|
||||
trackData.noaudio = false;
|
||||
trackData.group_id = mixer.group_id;
|
||||
trackData.oppositeMixer = oppositeMixer;
|
||||
context.jamClient.SessionSetUserName(participant.client_id,name);
|
||||
|
||||
} else { // No mixer to match, yet
|
||||
lookingForMixers[track.id] = participant.client_id;
|
||||
lookingForMixers.push({track: track, clientId: participant.client_id})
|
||||
trackData.noaudio = true;
|
||||
if (!(lookingForMixersTimer)) {
|
||||
logger.debug("waiting for mixer to show up for track: " + track.id)
|
||||
|
|
@ -940,14 +1079,12 @@
|
|||
}
|
||||
|
||||
var allowDelete = myTrack && index > 0;
|
||||
_addTrack(allowDelete, trackData, mixer);
|
||||
_addTrack(allowDelete, trackData, mixer, oppositeMixer);
|
||||
|
||||
// Show settings icons only for my tracks
|
||||
if (myTrack) {
|
||||
myTracks.push(trackData);
|
||||
}
|
||||
// TODO: UNCOMMENT THIS WHEN TESTING LOCALLY IN BROWSER
|
||||
//myTracks.push(trackData);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -955,7 +1092,7 @@
|
|||
addNewGearDialog = new context.JK.AddNewGearDialog(app, self);
|
||||
}
|
||||
|
||||
function connectTrackToMixer(trackSelector, clientId, mixerId, gainPercent, groupId) {
|
||||
function connectTrackToMixer(trackSelector, track, mixerId, gainPercent, groupId) {
|
||||
var vuOpts = $.extend({}, trackVuOpts);
|
||||
var faderOpts = $.extend({}, trackFaderOpts);
|
||||
faderOpts.faderId = mixerId;
|
||||
|
|
@ -963,16 +1100,21 @@
|
|||
var vuRightSelector = trackSelector + " .track-vu-right";
|
||||
var faderSelector = trackSelector + " .track-gain";
|
||||
var $fader = $(faderSelector).attr('mixer-id', mixerId).data('groupId', groupId)
|
||||
if(track.recordingDisabled) {
|
||||
$fader.data('recording-disabled', true).data('recording-opener', track.recordingOpener) // this we be applied later to the fader handle $element
|
||||
}
|
||||
var $track = $(trackSelector);
|
||||
// Set mixer-id attributes and render VU/Fader
|
||||
context.JK.VuHelpers.renderVU(vuLeftSelector, vuOpts);
|
||||
$track.find('.track-vu-left').attr('mixer-id', mixerId + '_vul').data('groupId', groupId)
|
||||
$track.find('.track-vu-left').attr('mixer-id', track.vuMixerId + '_vul').data('groupId', groupId)
|
||||
context.JK.VuHelpers.renderVU(vuRightSelector, vuOpts);
|
||||
$track.find('.track-vu-right').attr('mixer-id', mixerId + '_vur').data('groupId', groupId)
|
||||
$track.find('.track-vu-right').attr('mixer-id', track.vuMixerId + '_vur').data('groupId', groupId)
|
||||
context.JK.FaderHelpers.renderFader($fader, faderOpts);
|
||||
// Set gain position
|
||||
context.JK.FaderHelpers.setFaderValue(mixerId, gainPercent);
|
||||
$fader.on('fader_change', faderChanged);
|
||||
|
||||
return $track;
|
||||
}
|
||||
|
||||
// Function called on an interval when participants change. Mixers seem to
|
||||
|
|
@ -984,83 +1126,61 @@
|
|||
_updateMixers();
|
||||
var usedMixers = {};
|
||||
var keysToDelete = [];
|
||||
for (var key in lookingForMixers) {
|
||||
var clientId = lookingForMixers[key];
|
||||
var currentMixers = _groupedMixersForClientId(
|
||||
clientId,
|
||||
[
|
||||
ChannelGroupIds.AudioInputMusicGroup,
|
||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
||||
ChannelGroupIds.UserMusicInputGroup
|
||||
],
|
||||
usedMixers, sessionModel.getMixMode());
|
||||
context._.each(lookingForMixers, function(data) {
|
||||
var clientId = data.clientId;
|
||||
var track = data.track;
|
||||
|
||||
var oppositeMixers = _groupedMixersForClientId(
|
||||
clientId,
|
||||
[
|
||||
ChannelGroupIds.AudioInputMusicGroup,
|
||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
||||
ChannelGroupIds.UserMusicInputGroup
|
||||
],
|
||||
usedMixers, !sessionModel.getMixMode());
|
||||
var myTrack = app.clientId == clientId;
|
||||
|
||||
var mixer = null;
|
||||
var oppositeMixer = null;
|
||||
if(currentMixers) {
|
||||
if(currentMixers[ChannelGroupIds.AudioInputMusicGroup]) {
|
||||
mixer = currentMixers[ChannelGroupIds.AudioInputMusicGroup][0]
|
||||
oppositeMixer = oppositeMixers[ChannelGroupIds.AudioInputMusicGroup][0]
|
||||
}
|
||||
else if(sessionModel.isMasterMixMode() && currentMixers[ChannelGroupIds.PeerAudioInputMusicGroup]) {
|
||||
mixer = currentMixers[ChannelGroupIds.PeerAudioInputMusicGroup][0]
|
||||
oppositeMixer = oppositeMixers[ChannelGroupIds.UserMusicInputGroup][0]
|
||||
}
|
||||
else if(!sessionModel.isMasterMixMode() && currentMixers[ChannelGroupIds.UserMusicInputGroup]) {
|
||||
mixer = currentMixers[ChannelGroupIds.UserMusicInputGroup][0]
|
||||
oppositeMixer = oppositeMixers[ChannelGroupIds.PeerAudioInputMusicGroup][0]
|
||||
}
|
||||
var mixerData = findMixerForTrack(clientId, track, myTrack)
|
||||
|
||||
var mixer = mixerData.mixer;
|
||||
var oppositeMixer = mixerData.oppositeMixer;
|
||||
var vuMixer = mixerData.vuMixer;
|
||||
var muteMixer = mixerData.muteMixer;
|
||||
|
||||
if (mixer && oppositeMixer) {
|
||||
var participant = (sessionModel.getParticipant(clientId) || {name:'unknown'}).name;
|
||||
logger.debug("found mixer=" + mixer.id + ", participant=" + participant)
|
||||
usedMixers[mixer.id] = true;
|
||||
keysToDelete.push(data);
|
||||
var gainPercent = percentFromMixerValue(
|
||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||
var trackSelector = 'div.track[track-id="' + track.id + '"]';
|
||||
|
||||
connectTrackToMixer(trackSelector, track, mixer.id, gainPercent, mixer.group_id);
|
||||
var $track = $('div.track[client-id="' + clientId + '"]');
|
||||
var $trackIconMute = $track.find('.track-icon-mute')
|
||||
$trackIconMute.attr('mixer-id', muteMixer.id).data('mixer', mixer).data('opposite-mixer', oppositeMixer)
|
||||
$trackIconMute.muteSelector().on(EVENTS.MUTE_SELECTED, trackMuteSelected)
|
||||
|
||||
// hide overlay for all tracks associated with this client id (if one mixer is present, then all tracks are valid)
|
||||
$('.disabled-track-overlay', $track).hide();
|
||||
$('.track-connection', $track).removeClass('red yellow green').addClass('grey');
|
||||
// Set mute state
|
||||
_toggleVisualMuteControl($trackIconMute, mixer.mute || oppositeMixer.mute);
|
||||
}
|
||||
else {
|
||||
// if 1 second has gone by and still no mixer, then we gray the participant's tracks
|
||||
if(lookingForMixersCount == 2) {
|
||||
var $track = $('div.track[client-id="' + clientId + '"]');
|
||||
$('.disabled-track-overlay', $track).show();
|
||||
$('.track-connection', $track).removeClass('red yellow green').addClass('red');
|
||||
}
|
||||
if (mixer) {
|
||||
var participant = (sessionModel.getParticipant(clientId) || {name:'unknown'}).name;
|
||||
logger.debug("found mixer=" + mixer.id + ", participant=" + participant)
|
||||
usedMixers[mixer.id] = true;
|
||||
keysToDelete.push(key);
|
||||
var gainPercent = percentFromMixerValue(
|
||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||
var trackSelector = 'div.track[track-id="' + key + '"]';
|
||||
|
||||
connectTrackToMixer(trackSelector, key, mixer.id, gainPercent, mixer.group_id);
|
||||
var $track = $('div.track[client-id="' + clientId + '"]');
|
||||
var $trackIconMute = $track.find('.track-icon-mute')
|
||||
$trackIconMute.attr('mixer-id', mixer.id).attr('opposite-mixer-id', oppositeMixer.id).data('mixer', mixer).data('opposite-mixer', oppositeMixer)
|
||||
$trackIconMute.muteSelector().on(EVENTS.MUTE_SELECTED, trackMuteSelected)
|
||||
|
||||
// hide overlay for all tracks associated with this client id (if one mixer is present, then all tracks are valid)
|
||||
$('.disabled-track-overlay', $track).hide();
|
||||
$('.track-connection', $track).removeClass('red yellow green').addClass('grey');
|
||||
// Set mute state
|
||||
_toggleVisualMuteControl($trackIconMute, mixer, oppositeMixer);
|
||||
}
|
||||
else {
|
||||
// if 1 second has gone by and still no mixer, then we gray the participant's tracks
|
||||
if(lookingForMixersCount == 2) {
|
||||
var $track = $('div.track[client-id="' + clientId + '"]');
|
||||
$('.disabled-track-overlay', $track).show();
|
||||
$('.track-connection', $track).removeClass('red yellow green').addClass('red');
|
||||
}
|
||||
var participant = (sessionModel.getParticipant(clientId) || { user: {name: 'unknown'}}).user.name;
|
||||
logger.debug("still looking for mixer for participant=" + participant + ", clientId=" + clientId)
|
||||
}
|
||||
}
|
||||
var participant = (sessionModel.getParticipant(clientId) || { user: {name: 'unknown'}}).user.name;
|
||||
logger.debug("still looking for mixer for participant=" + participant + ", clientId=" + clientId)
|
||||
}
|
||||
})
|
||||
|
||||
for (var i=0; i<keysToDelete.length; i++) {
|
||||
delete lookingForMixers[keysToDelete[i]];
|
||||
var index = lookingForMixers.indexOf(keysToDelete[i]);
|
||||
lookingForMixers.splice(index, 1);
|
||||
}
|
||||
|
||||
if (context.JK.dlen(lookingForMixers) === 0 ||
|
||||
if (lookingForMixers.length === 0 ||
|
||||
lookingForMixersCount > 20) {
|
||||
lookingForMixersCount = 0;
|
||||
lookingForMixers = {};
|
||||
lookingForMixers = []
|
||||
context.clearTimeout(lookingForMixersTimer);
|
||||
lookingForMixersTimer = null;
|
||||
}
|
||||
|
|
@ -1068,7 +1188,7 @@
|
|||
|
||||
// Given a mixerID and a value between 0.0-1.0,
|
||||
// light up the proper VU lights.
|
||||
function _updateVU(mixerId, value) {
|
||||
function _updateVU(mixerId, value, isClipping) {
|
||||
|
||||
// Special-case for mono tracks. If mono, and it's a _vul id,
|
||||
// update both sides, otherwise do nothing.
|
||||
|
|
@ -1076,7 +1196,7 @@
|
|||
var selector;
|
||||
var pureMixerId = mixerId.replace("_vul", "");
|
||||
pureMixerId = pureMixerId.replace("_vur", "");
|
||||
var mixer = getMixer(pureMixerId, sessionModel.getMixMode());
|
||||
var mixer = getMixer(pureMixerId);
|
||||
if (mixer) {
|
||||
if (!(mixer.stereo)) { // mono track
|
||||
if (mixerId.substr(-4) === "_vul") {
|
||||
|
|
@ -1094,7 +1214,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function _addTrack(allowDelete, trackData, mixer) {
|
||||
function _addTrack(allowDelete, trackData, mixer, oppositeMixer) {
|
||||
|
||||
var parentSelector = '#session-mytracks-container';
|
||||
var $destination = $(parentSelector);
|
||||
|
|
@ -1108,7 +1228,7 @@
|
|||
var audioOverlay = $('.disabled-track-overlay', newTrack);
|
||||
var $trackIconMute = newTrack.find('.track-icon-mute')
|
||||
$trackIconMute.muteSelector().on(EVENTS.MUTE_SELECTED, trackMuteSelected)
|
||||
$trackIconMute.data('mixer', mixer)
|
||||
$trackIconMute.data('mixer', mixer).data('opposite-mixer', oppositeMixer)
|
||||
|
||||
audioOverlay.hide(); // always start with overlay hidden, and only show if no audio persists
|
||||
$destination.append(newTrack);
|
||||
|
|
@ -1116,7 +1236,7 @@
|
|||
// Render VU meters and gain fader
|
||||
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
||||
var gainPercent = trackData.gainPercent || 0;
|
||||
connectTrackToMixer(trackSelector, trackData.clientId, trackData.mixerId, gainPercent, trackData.group_id);
|
||||
connectTrackToMixer(trackSelector, trackData, trackData.mixerId, gainPercent, trackData.group_id);
|
||||
|
||||
var $closeButton = $('#div-track-close', 'div[track-id="' + trackData.trackId + '"]');
|
||||
if (!allowDelete) {
|
||||
|
|
@ -1148,8 +1268,11 @@
|
|||
// Render VU meters and gain fader
|
||||
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
||||
var gainPercent = trackData.gainPercent || 0;
|
||||
connectTrackToMixer(trackSelector, trackData.clientId, trackData.mixerId, gainPercent, null);
|
||||
|
||||
var $track = connectTrackToMixer(trackSelector, trackData, trackData.mixerId, gainPercent, null);
|
||||
var $trackIconMute = $track.find('.track-icon-mute')
|
||||
if(trackData.recordingDisabled) {
|
||||
$trackIconMute.data('recording-disabled', true).data('recording-opener', trackData.recordingOpener)
|
||||
}
|
||||
tracks[trackData.trackId] = new context.JK.SessionTrack(trackData.clientId);
|
||||
}
|
||||
|
||||
|
|
@ -1187,62 +1310,69 @@
|
|||
//_toggleVisualMuteControl($muteControl, isMuted);
|
||||
}
|
||||
|
||||
function handleBridgeCallback() {
|
||||
function handleBridgeCallback(vuData) {
|
||||
var j;
|
||||
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 === 'connection_status') {
|
||||
// Connection Quality Change
|
||||
var connectionClass = 'green';
|
||||
if (value < 7) {
|
||||
connectionClass = 'yellow';
|
||||
}
|
||||
if (value < 4) {
|
||||
connectionClass = 'red';
|
||||
}
|
||||
var clientId = _clientIdForUserInputMixer(mixerId, sessionModel.getMixMode());
|
||||
var vuInfo = null;
|
||||
for (j = 0; j < vuData.length; j++) {
|
||||
vuInfo = vuData[j];
|
||||
var eventName = vuInfo[0];
|
||||
var vuVal = 0.0;
|
||||
if(eventName === "vu") {
|
||||
var mixerId = vuInfo[1];
|
||||
var leftValue = vuInfo[2];
|
||||
var leftClipping = vuInfo[3];
|
||||
var rightValue = vuInfo[4];
|
||||
var rightClipping = vuInfo[5];
|
||||
// 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
|
||||
_updateVU(mixerId + "_vul", (leftValue + 80) / 100, leftClipping);
|
||||
_updateVU(mixerId + "_vur", (rightValue + 80) / 100, rightClipping);
|
||||
}
|
||||
else if(eventName === 'connection_status') {
|
||||
var mixerId = vuInfo[1];
|
||||
var value = vuInfo[2];
|
||||
|
||||
if(clientId) {
|
||||
var $connection = $('.session-track[client-id="' + clientId + '"] .track-connection');
|
||||
if($connection.length == 0) {
|
||||
logger.debug("connection status: looking for clientId: " + clientId + ", mixer: " + mixerId)
|
||||
}
|
||||
else {
|
||||
$connection.removeClass('red yellow green grey');
|
||||
$connection.addClass(connectionClass);
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
// Connection Quality Change
|
||||
var connectionClass = 'green';
|
||||
if (value < 7) {
|
||||
connectionClass = 'yellow';
|
||||
}
|
||||
if (value < 4) {
|
||||
connectionClass = 'red';
|
||||
}
|
||||
var mixerPair = getMixerByTrackId(mixerId);
|
||||
|
||||
var clientId = mixerPair ? mixerPair.master.client_id : null;
|
||||
|
||||
if(clientId) {
|
||||
var $connection = $('.session-track[client-id="' + clientId + '"] .track-connection');
|
||||
if($connection.length == 0) {
|
||||
logger.debug("connection status: looking for clientId: " + clientId + ", mixer: " + mixerId)
|
||||
}
|
||||
else {
|
||||
$connection.removeClass('red yellow green grey');
|
||||
$connection.addClass(connectionClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
logger.debug('non-vu event: ' + JSON.stringify(vuInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function deleteSession(evt) {
|
||||
var sessionId = $(evt.currentTarget).attr("action-id");
|
||||
|
|
@ -1265,8 +1395,8 @@
|
|||
sessionModel.deleteTrack(sessionId, trackId);
|
||||
}
|
||||
|
||||
function _toggleVisualMuteControl($control, currentMixer, oppositeMixer) {
|
||||
if (currentMixer.mute) {
|
||||
function _toggleVisualMuteControl($control, mute) {
|
||||
if (mute) {
|
||||
$control.removeClass('enabled');
|
||||
$control.addClass('muted');
|
||||
} else {
|
||||
|
|
@ -1275,10 +1405,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
function _toggleAudioMute(mixerId, muting) {
|
||||
function _toggleAudioMute(mixerId, muting, mode) {
|
||||
fillTrackVolumeObject(mixerId);
|
||||
context.trackVolumeObject.mute = muting;
|
||||
context.jamClient.SessionSetControlState(mixerId, sessionModel.getMixerMode());
|
||||
|
||||
if(mode === undefined) {
|
||||
mode = sessionModel.getMixMode();
|
||||
}
|
||||
context.jamClient.SessionSetControlState(mixerId, mode);
|
||||
}
|
||||
|
||||
function showMuteDropdowns($control) {
|
||||
|
|
@ -1292,20 +1426,28 @@
|
|||
|
||||
// track icons have a special mute behavior
|
||||
if($control.is('.track-icon-mute')) {
|
||||
$.each(mixerIds, function(i,v) {
|
||||
if(muting) {
|
||||
// show insta-dropdown providing two options for mute
|
||||
showMuteDropdowns($control);
|
||||
}
|
||||
else {
|
||||
_toggleAudioMute(v, muting);
|
||||
}
|
||||
});
|
||||
|
||||
if(!muting) {
|
||||
_toggleVisualMuteControl($control, muting);
|
||||
var recordingDisabled = $control.data('recording-disabled');
|
||||
if(recordingDisabled) {
|
||||
var recordingOpener = $control.data('recording-opener');
|
||||
context.JK.prodBubble($control, 'recording-controls-disabled', {recordingOpener:recordingOpener}, {positions:['bottom'], offsetParent: $control.closest('.screen')})
|
||||
return false;
|
||||
}
|
||||
|
||||
$.each(mixerIds, function(i,v) {
|
||||
var mixerId = v;
|
||||
// behavior: if this is the user's track in personal mode, then we mute the track globally
|
||||
// otherwise, for any other track (user+master mode, or remote track in any mode)
|
||||
// we just mute the type of track for that mode
|
||||
var mixer = $control.data('mixer');
|
||||
var oppositeMixer = $control.data('opposite-mixer')
|
||||
|
||||
_toggleAudioMute(mixerId, muting, getMixer(mixerId).mode)
|
||||
|
||||
// look for all controls matching this mixer id (important when it's personal mode + UserMusicInputGroup)
|
||||
var $controls = $screen.find('.track-icon-mute[mixer-id=' + mixerId +']');
|
||||
_toggleVisualMuteControl($controls, muting);
|
||||
});
|
||||
}
|
||||
else {
|
||||
$.each(mixerIds, function(i,v) {
|
||||
|
|
@ -1319,29 +1461,23 @@
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
var mixer = getMixer(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;
|
||||
}
|
||||
|
||||
// Given a mixer's min/max and current value, return it as
|
||||
|
|
@ -1394,7 +1530,7 @@
|
|||
context.jamClient.SessionSetMasterLocalMix(dbValue);
|
||||
// context.jamClient.SessionSetMasterLocalMix(sliderValue);
|
||||
} else {
|
||||
context.jamClient.SessionSetControlState(mixerId, sessionModel.getMixerMode());
|
||||
context.jamClient.SessionSetControlState(mixerId, sessionModel.getMixMode());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
var startTime = null;
|
||||
var joinDeferred = null;
|
||||
|
||||
var mixerMode = MIX_MODES.GLOBAL;
|
||||
var mixerMode = MIX_MODES.PERSONAL;
|
||||
|
||||
server.registerOnSocketClosed(onWebsocketDisconnected);
|
||||
|
||||
|
|
@ -110,7 +110,7 @@
|
|||
// see if we already have tracks; if so, we need to run with these
|
||||
var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
|
||||
if(inputTracks.length > 0) {
|
||||
logger.debug("on page enter, audio is already running")
|
||||
logger.debug("on page enter, tracks are already available")
|
||||
sessionPageEnterDeferred.resolve(inputTracks);
|
||||
var deferred = sessionPageEnterDeferred;
|
||||
sessionPageEnterDeferred = null;
|
||||
|
|
@ -506,6 +506,10 @@
|
|||
return mixerMode == MIX_MODES.MASTER;
|
||||
}
|
||||
|
||||
function isPersonalMixMode() {
|
||||
return mixerMode == MIX_MODES.PERSONAL;
|
||||
}
|
||||
|
||||
function getMixMode() {
|
||||
return mixerMode;
|
||||
}
|
||||
|
|
@ -668,6 +672,7 @@
|
|||
this.inSession = inSession;
|
||||
this.setMixerMode = setMixerMode;
|
||||
this.isMasterMixMode = isMasterMixMode;
|
||||
this.isPersonalMixMode = isPersonalMixMode;
|
||||
this.getMixMode = getMixMode;
|
||||
|
||||
// ALERT HANDLERS
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@
|
|||
|
||||
localMusicTracks = context.JK.TrackHelpers.getTracks(jamClient, 2);
|
||||
|
||||
console.log("getUserTracks", localMusicTracks)
|
||||
var trackObjects = [];
|
||||
|
||||
for (i=0; i < localMusicTracks.length; i++) {
|
||||
var track = {};
|
||||
track.client_track_id = localMusicTracks[i].id;
|
||||
track.client_resource_id = localMusicTracks[i].rid;
|
||||
|
||||
if(localMusicTracks[i].instrument_id === 0) {
|
||||
track.instrument_id = context.JK.server_to_client_instrument_map["Other"].server_id;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
*/
|
||||
renderVU: function(selector, userOptions) {
|
||||
selector = $(selector);
|
||||
|
||||
|
||||
/**
|
||||
* The default options for rendering a VU
|
||||
*/
|
||||
|
|
@ -36,9 +38,13 @@
|
|||
templateSelector = "#template-vu-h";
|
||||
}
|
||||
var templateSource = $(templateSelector).html();
|
||||
selector.empty();
|
||||
|
||||
selector.html(context._.template(templateSource, options, {variable: 'data'}));
|
||||
selector.each(function() {
|
||||
var $track = $(this);
|
||||
$track.empty();
|
||||
$track.html(context._.template(templateSource, options, {variable: 'data'}));
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -48,41 +54,45 @@
|
|||
updateVU: function ($selector, value) {
|
||||
// There are 13 VU lights. Figure out how many to
|
||||
// light based on the incoming value.
|
||||
var countSelector = 'tr';
|
||||
var horizontal = ($selector.find('table.horizontal').length);
|
||||
if (horizontal) {
|
||||
countSelector = 'td';
|
||||
}
|
||||
|
||||
var lightCount = $selector.find(countSelector).length;
|
||||
var i = 0;
|
||||
var state = 'on';
|
||||
var lights = Math.round(value * lightCount);
|
||||
var redSwitch = Math.round(lightCount * 0.6666667);
|
||||
|
||||
var $light = null;
|
||||
var colorClass = 'vu-green-';
|
||||
var lightSelectorPrefix = $selector.find('td.vu');
|
||||
var thisLightSelector = null;
|
||||
|
||||
// Remove all light classes from all lights
|
||||
var allLightsSelector = $selector.find('td.vulight');
|
||||
$(allLightsSelector).removeClass('vu-green-off vu-green-on vu-red-off vu-red-on');
|
||||
|
||||
// Set the lights
|
||||
for (i = 0; i < lightCount; i++) {
|
||||
colorClass = 'vu-green-';
|
||||
state = 'on';
|
||||
if (i >= redSwitch) {
|
||||
colorClass = 'vu-red-';
|
||||
}
|
||||
if (i >= lights) {
|
||||
state = 'off';
|
||||
$selector.each(function() {
|
||||
var $track = $(this)
|
||||
var countSelector = 'tr';
|
||||
var horizontal = ($track.find('table.horizontal').length);
|
||||
if (horizontal) {
|
||||
countSelector = 'td';
|
||||
}
|
||||
|
||||
var lightIndex = horizontal ? i : lightCount - i - 1;
|
||||
allLightsSelector.eq(lightIndex).addClass(colorClass + state);
|
||||
}
|
||||
var lightCount = $track.find(countSelector).length;
|
||||
var i = 0;
|
||||
var state = 'on';
|
||||
var lights = Math.round(value * lightCount);
|
||||
var redSwitch = Math.round(lightCount * 0.6666667);
|
||||
|
||||
var $light = null;
|
||||
var colorClass = 'vu-green-';
|
||||
var lightSelectorPrefix = $track.find('td.vu');
|
||||
var thisLightSelector = null;
|
||||
|
||||
// Remove all light classes from all lights
|
||||
var allLightsSelector = $track.find('td.vulight');
|
||||
$(allLightsSelector).removeClass('vu-green-off vu-green-on vu-red-off vu-red-on');
|
||||
|
||||
// Set the lights
|
||||
for (i = 0; i < lightCount; i++) {
|
||||
colorClass = 'vu-green-';
|
||||
state = 'on';
|
||||
if (i >= redSwitch) {
|
||||
colorClass = 'vu-red-';
|
||||
}
|
||||
if (i >= lights) {
|
||||
state = 'off';
|
||||
}
|
||||
|
||||
var lightIndex = horizontal ? i : lightCount - i - 1;
|
||||
allLightsSelector.eq(lightIndex).addClass(colorClass + state);
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -373,7 +373,8 @@ class ApiMusicSessionsController < ApiController
|
|||
params[:connection_id],
|
||||
params[:instrument_id],
|
||||
params[:sound],
|
||||
params[:client_track_id])
|
||||
params[:client_track_id],
|
||||
params[:client_resource_id])
|
||||
|
||||
respond_with @track, responder: ApiResponder, :status => 201, :location => api_session_track_detail_url(@track.connection.music_session, @track)
|
||||
end
|
||||
|
|
@ -384,7 +385,8 @@ class ApiMusicSessionsController < ApiController
|
|||
nil,
|
||||
params[:instrument_id],
|
||||
params[:sound],
|
||||
params[:client_track_id])
|
||||
params[:client_track_id],
|
||||
params[:client_resource_id])
|
||||
|
||||
respond_with @track, responder: ApiResponder, :status => 200
|
||||
|
||||
|
|
|
|||
|
|
@ -45,14 +45,14 @@ else
|
|||
|
||||
child(:connections => :participants) {
|
||||
collection @music_sessions, :object_root => false
|
||||
attributes :ip_address, :client_id, :joined_session_at, :audio_latency
|
||||
attributes :ip_address, :client_id, :joined_session_at, :audio_latency, :id
|
||||
|
||||
node :user do |connection|
|
||||
{ :id => connection.user.id, :photo_url => connection.user.photo_url, :name => connection.user.name, :is_friend => connection.user.friends?(current_user), :connection_state => connection.aasm_state }
|
||||
end
|
||||
|
||||
child(:tracks => :tracks) {
|
||||
attributes :id, :connection_id, :instrument_id, :sound, :client_track_id, :updated_at
|
||||
attributes :id, :connection_id, :instrument_id, :sound, :client_track_id, :client_resource_id, :updated_at
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ else
|
|||
end
|
||||
|
||||
child(:tracks => :tracks) {
|
||||
attributes :id, :connection_id, :instrument_id, :sound, :client_track_id, :updated_at
|
||||
attributes :id, :connection_id, :instrument_id, :sound, :client_track_id, :client_resource_id, :updated_at
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,4 +162,12 @@
|
|||
<div class="file-sync-delayed-deletion">
|
||||
The files associated with this recording will be deleted as soon as your client has uploaded your tracks and stream mix from this recording.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-help-recording-controls-disabled">
|
||||
{% if(data.recordingOpener) { %}
|
||||
Switch <b>MIX:</b> to <b>Master</b> mode to have control over volume levels.
|
||||
{% } else { %}
|
||||
Only the person who opened the recording can control the volume levels.
|
||||
{% } %}
|
||||
</script>
|
||||
|
|
@ -151,8 +151,8 @@
|
|||
<!-- Track Template -->
|
||||
<script type="text/template" id="template-session-track">
|
||||
<div track-id="{trackId}" class="session-track track" client-id="{clientId}">
|
||||
<div class="track-vu-left" mixer-id="{mixerId}_vul"></div>
|
||||
<div class="track-vu-right" mixer-id="{mixerId}_vur"></div>
|
||||
<div class="track-vu-left" mixer-id="{vuMixerId}_vul"></div>
|
||||
<div class="track-vu-right" mixer-id="{vuMixerId}_vur"></div>
|
||||
<div class="track-label">{name}</div>
|
||||
<div id="div-track-close" track-id="{trackId}" class="track-close op30">
|
||||
<%= image_tag "content/icon_closetrack.png", {:width => 12, :height => 12} %>
|
||||
|
|
@ -173,7 +173,7 @@
|
|||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div class="track-icon-mute {muteClass}" control="mute" mixer-id="{mixerId}">
|
||||
<div class="track-icon-mute {muteClass}" control="mute" mixer-id="{muteMixerId}">
|
||||
</div>
|
||||
<!-- TODO - connection class from curly param -->
|
||||
<div mixer-id="{mixerId}_connection" class="track-connection grey">CONNECTION</div>
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ FactoryGirl.define do
|
|||
factory :track, :class => JamRuby::Track do
|
||||
sound "mono"
|
||||
sequence(:client_track_id) { |n| "client_track_id_seq_#{n}"}
|
||||
sequence(:client_resource_id) { |n| "resource_id#{n}"}
|
||||
end
|
||||
|
||||
factory :video_source, :class => JamRuby::VideoSource do
|
||||
|
|
|
|||
Loading…
Reference in New Issue