* VRFS-1491 - finishing up dealing with refactor of monitor vs master tracks
This commit is contained in:
parent
76adc44a50
commit
eedc5ae970
|
|
@ -229,3 +229,4 @@ deletable_recordings.sql
|
||||||
jam_tracks.sql
|
jam_tracks.sql
|
||||||
shopping_carts.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.connection = self
|
||||||
t.sound = track["sound"]
|
t.sound = track["sound"]
|
||||||
t.client_track_id = track["client_track_id"]
|
t.client_track_id = track["client_track_id"]
|
||||||
|
t.client_resource_id = track["client_resource_id"]
|
||||||
t.save # todo what if it fails?
|
t.save # todo what if it fails?
|
||||||
self.tracks << t
|
self.tracks << t
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ module JamRuby
|
||||||
|
|
||||||
validates :sound, :inclusion => {:in => SOUND}
|
validates :sound, :inclusion => {:in => SOUND}
|
||||||
validates :connection, presence: true
|
validates :connection, presence: true
|
||||||
|
validates :client_track_id, presence: true
|
||||||
|
#validates :client_resource_id, presence: true
|
||||||
|
|
||||||
def user
|
def user
|
||||||
self.connection.user
|
self.connection.user
|
||||||
|
|
@ -89,6 +91,7 @@ module JamRuby
|
||||||
connection_track.instrument_id = track[:instrument_id]
|
connection_track.instrument_id = track[:instrument_id]
|
||||||
connection_track.sound = track[:sound]
|
connection_track.sound = track[:sound]
|
||||||
connection_track.client_track_id = track[:client_track_id]
|
connection_track.client_track_id = track[:client_track_id]
|
||||||
|
connection_track.client_resource_id = track[:client_resource_id]
|
||||||
|
|
||||||
result.push(connection_track)
|
result.push(connection_track)
|
||||||
|
|
||||||
|
|
@ -114,6 +117,7 @@ module JamRuby
|
||||||
connection_track.instrument_id = track[:instrument_id]
|
connection_track.instrument_id = track[:instrument_id]
|
||||||
connection_track.sound = track[:sound]
|
connection_track.sound = track[:sound]
|
||||||
connection_track.client_track_id = track[:client_track_id]
|
connection_track.client_track_id = track[:client_track_id]
|
||||||
|
connection_track.client_resource_id = track[:client_resource_id]
|
||||||
if connection_track.save
|
if connection_track.save
|
||||||
result.push(connection_track)
|
result.push(connection_track)
|
||||||
else
|
else
|
||||||
|
|
@ -131,7 +135,7 @@ module JamRuby
|
||||||
result
|
result
|
||||||
end
|
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?
|
if id.nil?
|
||||||
track = Track.new
|
track = Track.new
|
||||||
track.connection_id = connection_id
|
track.connection_id = connection_id
|
||||||
|
|
@ -151,6 +155,10 @@ module JamRuby
|
||||||
track.client_track_id = client_track_id
|
track.client_track_id = client_track_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless client_resource_id.nil?
|
||||||
|
track.client_resource_id = resource_id
|
||||||
|
end
|
||||||
|
|
||||||
track.updated_at = Time.now
|
track.updated_at = Time.now
|
||||||
track.save
|
track.save
|
||||||
return track
|
return track
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@ FactoryGirl.define do
|
||||||
factory :track, :class => JamRuby::Track do
|
factory :track, :class => JamRuby::Track do
|
||||||
sound "mono"
|
sound "mono"
|
||||||
sequence(:client_track_id) { |n| "client_track_id#{n}"}
|
sequence(:client_track_id) { |n| "client_track_id#{n}"}
|
||||||
|
sequence(:client_resource_id) { |n| "resource_id#{n}"}
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :video_source, :class => JamRuby::VideoSource do
|
factory :video_source, :class => JamRuby::VideoSource do
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ describe Track do
|
||||||
track.id.should_not be_nil
|
track.id.should_not be_nil
|
||||||
connection.tracks.length.should == 1
|
connection.tracks.length.should == 1
|
||||||
set_updated_at(track, 1.days.ago)
|
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
|
tracks.length.should == 1
|
||||||
found = tracks[0]
|
found = tracks[0]
|
||||||
expect(found.id).to eq track.id
|
expect(found.id).to eq track.id
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,18 @@
|
||||||
var logger = g.JK.logger;
|
var logger = g.JK.logger;
|
||||||
|
|
||||||
function faderClick(e) {
|
function faderClick(e) {
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
var $fader = $(this);
|
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');
|
draggingOrientation = $fader.attr('orientation');
|
||||||
var offset = $fader.offset();
|
var offset = $fader.offset();
|
||||||
var position = { top: e.pageY - offset.top, left: e.pageX - offset.left}
|
var position = { top: e.pageY - offset.top, left: e.pageX - offset.left}
|
||||||
|
|
@ -117,6 +126,14 @@
|
||||||
$draggingFaderHandle = $(this);
|
$draggingFaderHandle = $(this);
|
||||||
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
|
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
|
||||||
draggingOrientation = $draggingFader.attr('orientation');
|
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) {
|
function onFaderDragStop(e, ui) {
|
||||||
|
|
@ -162,13 +179,15 @@
|
||||||
|
|
||||||
selector.html(g._.template(templateSource, options));
|
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({
|
selector.find('div[control="fader-handle"]').draggable({
|
||||||
drag: onFaderDrag,
|
drag: onFaderDrag,
|
||||||
start: onFaderDragStart,
|
start: onFaderDragStart,
|
||||||
stop: onFaderDragStop,
|
stop: onFaderDragStop,
|
||||||
containment: "parent",
|
containment: "parent",
|
||||||
axis: options.faderType === 'horizontal' ? 'x' : 'y'
|
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
|
// Embed any custom styles, applied to the .fader below selector
|
||||||
if ("style" in options) {
|
if ("style" in options) {
|
||||||
|
|
|
||||||
|
|
@ -392,6 +392,10 @@
|
||||||
logger.debug("Fake JamClient: SessionAudioResync()");
|
logger.debug("Fake JamClient: SessionAudioResync()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SessionGetAllControlState(isMasterOrPersonal) {
|
||||||
|
var mixerIds = SessionGetIDs()
|
||||||
|
return SessionGetControlState(mixerIds, isMasterOrPersonal);
|
||||||
|
}
|
||||||
function SessionGetControlState(mixerIds, isMasterOrPersonal) {
|
function SessionGetControlState(mixerIds, isMasterOrPersonal) {
|
||||||
dbg("SessionGetControlState");
|
dbg("SessionGetControlState");
|
||||||
var groups = [0, 1, 2, 3, 7, 9];
|
var groups = [0, 1, 2, 3, 7, 9];
|
||||||
|
|
@ -416,9 +420,9 @@
|
||||||
response.push({
|
response.push({
|
||||||
client_id: clientIds[i],
|
client_id: clientIds[i],
|
||||||
group_id: groups[i],
|
group_id: groups[i],
|
||||||
id: mixerIds[i],
|
id: mixerIds[i] + (isMasterOrPersonal ? 'm' : 'p'),
|
||||||
master: true,
|
master: isMasterOrPersonal,
|
||||||
monitor: true,
|
monitor: !isMasterOrPersonal,
|
||||||
mute: false,
|
mute: false,
|
||||||
name: names[i],
|
name: names[i],
|
||||||
range_high: 20,
|
range_high: 20,
|
||||||
|
|
@ -428,7 +432,8 @@
|
||||||
volume_left: -40,
|
volume_left: -40,
|
||||||
volume_right:-40,
|
volume_right:-40,
|
||||||
instrument_id:50, // see globals.js
|
instrument_id:50, // see globals.js
|
||||||
mode: false
|
mode: isMasterOrPersonal,
|
||||||
|
rid: mixerIds[i]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
|
|
@ -504,7 +509,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function doCallbacks() {
|
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 = ["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",
|
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"];
|
"i~11~MultiChannel (FW AP Multi)~0^i~11~Multichannel (FW AP Multi)~2"];
|
||||||
|
|
@ -518,7 +523,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var js = eventCallbackName + '(' + args.join(',') + ')';
|
var js = eventCallbackName + '(' + args.join(',') + ')';
|
||||||
eval(js);
|
//eval(js);
|
||||||
|
|
||||||
vuValue += vuChange;
|
vuValue += vuChange;
|
||||||
if (vuValue > 10 || vuValue < -70) { vuChange = vuChange * -1; }
|
if (vuValue > 10 || vuValue < -70) { vuChange = vuChange * -1; }
|
||||||
|
|
@ -912,6 +917,8 @@
|
||||||
// Session
|
// Session
|
||||||
this.SessionAddTrack = SessionAddTrack;
|
this.SessionAddTrack = SessionAddTrack;
|
||||||
this.SessionGetControlState = SessionGetControlState;
|
this.SessionGetControlState = SessionGetControlState;
|
||||||
|
this.SessionGetAllControlState = SessionGetAllControlState;
|
||||||
|
this.SessionSetUserName = SessionSetUserName;
|
||||||
this.SessionGetIDs = SessionGetIDs;
|
this.SessionGetIDs = SessionGetIDs;
|
||||||
this.RegisterRecordingManagerCallbacks = RegisterRecordingManagerCallbacks;
|
this.RegisterRecordingManagerCallbacks = RegisterRecordingManagerCallbacks;
|
||||||
this.RegisterRecordingCallbacks = RegisterRecordingCallbacks;
|
this.RegisterRecordingCallbacks = RegisterRecordingCallbacks;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
var myTracks = [];
|
var myTracks = [];
|
||||||
var masterMixers = [];
|
var masterMixers = [];
|
||||||
var personalMixers = [];
|
var personalMixers = [];
|
||||||
|
var allMixers = {};
|
||||||
|
var mixersByResourceId = {};
|
||||||
|
var mixersByTrackId = {};
|
||||||
var configureTrackDialog;
|
var configureTrackDialog;
|
||||||
var addNewGearDialog;
|
var addNewGearDialog;
|
||||||
var localRecordingsDialog = null;
|
var localRecordingsDialog = null;
|
||||||
|
|
@ -29,7 +32,7 @@
|
||||||
var currentMixerRangeMax = null;
|
var currentMixerRangeMax = null;
|
||||||
var lookingForMixersCount = 0;
|
var lookingForMixersCount = 0;
|
||||||
var lookingForMixersTimer = null;
|
var lookingForMixersTimer = null;
|
||||||
var lookingForMixers = {};
|
var lookingForMixers = [];
|
||||||
var $recordingTimer = null;
|
var $recordingTimer = null;
|
||||||
var recordingTimerInterval = null;
|
var recordingTimerInterval = null;
|
||||||
var startTimeDate = null;
|
var startTimeDate = null;
|
||||||
|
|
@ -454,15 +457,44 @@
|
||||||
* you must iterate. Convenience method to locate a particular
|
* you must iterate. Convenience method to locate a particular
|
||||||
* mixer by id.
|
* mixer by id.
|
||||||
*/
|
*/
|
||||||
function getMixer(mixerId, mixMode) {
|
function getMixer(mixerId) {
|
||||||
var foundMixer = null;
|
return allMixers[mixerId];
|
||||||
var mixers = mixMode == MIX_MODES.MASTER ? masterMixers : personalMixers;
|
}
|
||||||
$.each(mixers, function(index, mixer) {
|
|
||||||
if (mixer.id === mixerId) {
|
function getMixerByResourceId(resourceId, mode) {
|
||||||
foundMixer = mixer;
|
var mixerPair = mixersByResourceId[resourceId];
|
||||||
}
|
|
||||||
});
|
if(!mixerPair) {return null;}
|
||||||
return foundMixer;
|
|
||||||
|
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() {
|
function renderSession() {
|
||||||
|
|
@ -492,19 +524,58 @@
|
||||||
addNewGearDialog.initialize();
|
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() {
|
function _updateMixers() {
|
||||||
|
|
||||||
masterMixers = context.jamClient.SessionGetAllControlState(true);
|
masterMixers = context.jamClient.SessionGetAllControlState(true);
|
||||||
//var holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(masterMixerIds, true)});
|
|
||||||
//masterMixers = masterMixerIds.mixers;
|
|
||||||
|
|
||||||
personalMixers = context.jamClient.SessionGetAllControlState(false);
|
personalMixers = context.jamClient.SessionGetAllControlState(false);
|
||||||
//holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(personalMixerIds, false)});
|
|
||||||
//personalMixers = personalMixerIds.mixers;
|
|
||||||
|
|
||||||
console.log("masterMixers", masterMixers)
|
//logger.debug("masterMixers", masterMixers)
|
||||||
console.log("personalMixers", personalMixers)
|
//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
|
// Always add a hard-coded simplified 'mixer' for the L2M mix
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -565,7 +636,7 @@
|
||||||
//logger.debug("clientId", clientId, "groupIds", groupIds, "mixers", mixers)
|
//logger.debug("clientId", clientId, "groupIds", groupIds, "mixers", mixers)
|
||||||
var foundMixers = {};
|
var foundMixers = {};
|
||||||
var mixers = mixMode == MIX_MODES.MASTER ? masterMixers : personalMixers;
|
var mixers = mixMode == MIX_MODES.MASTER ? masterMixers : personalMixers;
|
||||||
console.log("_groupedMixersForClientId", mixers)
|
// console.log("_groupedMixersForClientId", mixers)
|
||||||
$.each(mixers, function(index, mixer) {
|
$.each(mixers, function(index, mixer) {
|
||||||
if (mixer.client_id === clientId) {
|
if (mixer.client_id === clientId) {
|
||||||
for (var i=0; i<groupIds.length; i++) {
|
for (var i=0; i<groupIds.length; i++) {
|
||||||
|
|
@ -694,16 +765,20 @@
|
||||||
$voiceChatGain.on('fader_change', faderChanged);
|
$voiceChatGain.on('fader_change', faderChanged);
|
||||||
context.JK.FaderHelpers.setFaderValue(mixer.id, gainPercent);
|
context.JK.FaderHelpers.setFaderValue(mixer.id, gainPercent);
|
||||||
//if (mixer.mute) {
|
//if (mixer.mute) {
|
||||||
_toggleVisualMuteControl($voiceChatMute, mixer, null);
|
_toggleVisualMuteControl($voiceChatMute, mixer.mute);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _renderLocalMediaTracks() {
|
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) {
|
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();
|
var recordedTracks = sessionModel.recordedTracks();
|
||||||
|
|
@ -791,7 +866,13 @@
|
||||||
trackData.gainPercent = gainPercent;
|
trackData.gainPercent = gainPercent;
|
||||||
trackData.muteClass = muteClass;
|
trackData.muteClass = muteClass;
|
||||||
trackData.mixerId = mixer.id;
|
trackData.mixerId = mixer.id;
|
||||||
|
trackData.vuMixerId = mixer.id;
|
||||||
|
trackData.muteMixerId = mixer.id;
|
||||||
|
|
||||||
|
if(sessionModel.isPersonalMixMode() || !isOpener) {
|
||||||
|
trackData.recordingDisabled = true;
|
||||||
|
trackData.recordingOpener = isOpener;
|
||||||
|
}
|
||||||
_addMediaTrack(trackData);
|
_addMediaTrack(trackData);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -817,16 +898,108 @@
|
||||||
var mixer = $muteControl.data('mixer')
|
var mixer = $muteControl.data('mixer')
|
||||||
var oppositeMixer = $muteControl.data('opposite-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());
|
logger.debug("muting tracks. current mixer id=" + mixer.id + ", opposite mixer id=" + oppositeMixer.id)
|
||||||
context.jamClient.SessionSetControlState(mixer.id, !sessionModel.isMasterMixMode());
|
|
||||||
|
var mixerPair = {}
|
||||||
|
if(sessionModel.isMasterMixMode()) {
|
||||||
|
mixerPair.master = mixer;
|
||||||
|
mixerPair.personal = oppositeMixer;
|
||||||
}
|
}
|
||||||
else if(mixer.group_id == ChannelGroupIds.UserMusicInputGroup || mixer.group_id == ChannelGroupIds.PeerAudioInputMusicGroup) {
|
else {
|
||||||
context.jamClient.SessionSetControlState(mixer.id, sessionModel.isMasterMixMode());
|
mixerPair.master = oppositeMixer;
|
||||||
context.jamClient.SessionSetControlState(oppositeMixer.id, !sessionModel.isMasterMixMode());
|
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() {
|
function _renderTracks() {
|
||||||
myTracks = [];
|
myTracks = [];
|
||||||
|
|
@ -834,6 +1007,8 @@
|
||||||
// Participants are here now, but the mixers don't update right away.
|
// Participants are here now, but the mixers don't update right away.
|
||||||
// Draw tracks from participants, then setup timers to look for the
|
// Draw tracks from participants, then setup timers to look for the
|
||||||
// mixers that go with those participants, if they're missing.
|
// mixers that go with those participants, if they're missing.
|
||||||
|
|
||||||
|
lookingForMixers = [] // clear this back out as we are restarting from scratch
|
||||||
lookingForMixersCount = 0;
|
lookingForMixersCount = 0;
|
||||||
$.each(sessionModel.participants(), function(index, participant) {
|
$.each(sessionModel.participants(), function(index, participant) {
|
||||||
|
|
||||||
|
|
@ -842,19 +1017,19 @@
|
||||||
name = participant.user.first_name + ' ' + participant.user.last_name;
|
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
|
// loop through all tracks for each participant
|
||||||
$.each(participant.tracks, function(index, track) {
|
$.each(participant.tracks, function(index, track) {
|
||||||
var instrumentIcon = context.JK.getInstrumentIcon45(track.instrument_id);
|
var instrumentIcon = context.JK.getInstrumentIcon45(track.instrument_id);
|
||||||
var photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
|
var photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
|
||||||
|
|
||||||
var myTrack = false;
|
|
||||||
|
|
||||||
// Default trackData to participant + no Mixer state.
|
// Default trackData to participant + no Mixer state.
|
||||||
var trackData = {
|
var trackData = {
|
||||||
trackId: track.id,
|
trackId: track.id,
|
||||||
connection_id: track.connection_id,
|
connection_id: track.connection_id,
|
||||||
|
client_track_id: track.client_track_id,
|
||||||
|
client_resource_id: track.client_resource_id,
|
||||||
clientId: participant.client_id,
|
clientId: participant.client_id,
|
||||||
name: name,
|
name: name,
|
||||||
instrumentIcon: instrumentIcon,
|
instrumentIcon: instrumentIcon,
|
||||||
|
|
@ -867,53 +1042,15 @@
|
||||||
preMasteredClass: ""
|
preMasteredClass: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the likely cause of multi-track problems.
|
var mixerData = findMixerForTrack(participant.client_id, track, myTrack)
|
||||||
// This should really become _mixersForClientId and return a list.
|
var mixer = mixerData.mixer;
|
||||||
// With multiple tracks, there will be more than one mixer for a
|
var vuMixer = mixerData.vuMixer;
|
||||||
// particular client, in a particular group, and I'll need to further
|
var muteMixer = mixerData.muteMixer;
|
||||||
// identify by track id or something similar.
|
var oppositeMixer = mixerData.oppositeMixer;
|
||||||
|
|
||||||
|
|
||||||
var currentMixers = _groupedMixersForClientId(
|
|
||||||
participant.client_id,
|
|
||||||
[
|
|
||||||
ChannelGroupIds.AudioInputMusicGroup,
|
|
||||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
|
||||||
ChannelGroupIds.UserMusicInputGroup
|
|
||||||
],
|
|
||||||
usedMixers, sessionModel.getMixMode());
|
|
||||||
|
|
||||||
var oppositeMixers = _groupedMixersForClientId(
|
if (mixer && oppositeMixer) {
|
||||||
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;
|
|
||||||
myTrack = (mixer.group_id === ChannelGroupIds.AudioInputMusicGroup);
|
myTrack = (mixer.group_id === ChannelGroupIds.AudioInputMusicGroup);
|
||||||
var gainPercent = percentFromMixerValue(
|
var gainPercent = percentFromMixerValue(
|
||||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||||
|
|
@ -925,13 +1062,15 @@
|
||||||
trackData.gainPercent = gainPercent;
|
trackData.gainPercent = gainPercent;
|
||||||
trackData.muteClass = muteClass;
|
trackData.muteClass = muteClass;
|
||||||
trackData.mixerId = mixer.id;
|
trackData.mixerId = mixer.id;
|
||||||
|
trackData.vuMixerId = vuMixer.id;
|
||||||
|
trackData.oppositeMixer = oppositeMixer;
|
||||||
|
trackData.muteMixerId = muteMixer.id;
|
||||||
trackData.noaudio = false;
|
trackData.noaudio = false;
|
||||||
trackData.group_id = mixer.group_id;
|
trackData.group_id = mixer.group_id;
|
||||||
trackData.oppositeMixer = oppositeMixer;
|
|
||||||
context.jamClient.SessionSetUserName(participant.client_id,name);
|
context.jamClient.SessionSetUserName(participant.client_id,name);
|
||||||
|
|
||||||
} else { // No mixer to match, yet
|
} else { // No mixer to match, yet
|
||||||
lookingForMixers[track.id] = participant.client_id;
|
lookingForMixers.push({track: track, clientId: participant.client_id})
|
||||||
trackData.noaudio = true;
|
trackData.noaudio = true;
|
||||||
if (!(lookingForMixersTimer)) {
|
if (!(lookingForMixersTimer)) {
|
||||||
logger.debug("waiting for mixer to show up for track: " + track.id)
|
logger.debug("waiting for mixer to show up for track: " + track.id)
|
||||||
|
|
@ -940,14 +1079,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var allowDelete = myTrack && index > 0;
|
var allowDelete = myTrack && index > 0;
|
||||||
_addTrack(allowDelete, trackData, mixer);
|
_addTrack(allowDelete, trackData, mixer, oppositeMixer);
|
||||||
|
|
||||||
// Show settings icons only for my tracks
|
// Show settings icons only for my tracks
|
||||||
if (myTrack) {
|
if (myTrack) {
|
||||||
myTracks.push(trackData);
|
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);
|
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 vuOpts = $.extend({}, trackVuOpts);
|
||||||
var faderOpts = $.extend({}, trackFaderOpts);
|
var faderOpts = $.extend({}, trackFaderOpts);
|
||||||
faderOpts.faderId = mixerId;
|
faderOpts.faderId = mixerId;
|
||||||
|
|
@ -963,16 +1100,21 @@
|
||||||
var vuRightSelector = trackSelector + " .track-vu-right";
|
var vuRightSelector = trackSelector + " .track-vu-right";
|
||||||
var faderSelector = trackSelector + " .track-gain";
|
var faderSelector = trackSelector + " .track-gain";
|
||||||
var $fader = $(faderSelector).attr('mixer-id', mixerId).data('groupId', groupId)
|
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);
|
var $track = $(trackSelector);
|
||||||
// Set mixer-id attributes and render VU/Fader
|
// Set mixer-id attributes and render VU/Fader
|
||||||
context.JK.VuHelpers.renderVU(vuLeftSelector, vuOpts);
|
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);
|
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);
|
context.JK.FaderHelpers.renderFader($fader, faderOpts);
|
||||||
// Set gain position
|
// Set gain position
|
||||||
context.JK.FaderHelpers.setFaderValue(mixerId, gainPercent);
|
context.JK.FaderHelpers.setFaderValue(mixerId, gainPercent);
|
||||||
$fader.on('fader_change', faderChanged);
|
$fader.on('fader_change', faderChanged);
|
||||||
|
|
||||||
|
return $track;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function called on an interval when participants change. Mixers seem to
|
// Function called on an interval when participants change. Mixers seem to
|
||||||
|
|
@ -984,83 +1126,61 @@
|
||||||
_updateMixers();
|
_updateMixers();
|
||||||
var usedMixers = {};
|
var usedMixers = {};
|
||||||
var keysToDelete = [];
|
var keysToDelete = [];
|
||||||
for (var key in lookingForMixers) {
|
context._.each(lookingForMixers, function(data) {
|
||||||
var clientId = lookingForMixers[key];
|
var clientId = data.clientId;
|
||||||
var currentMixers = _groupedMixersForClientId(
|
var track = data.track;
|
||||||
clientId,
|
|
||||||
[
|
|
||||||
ChannelGroupIds.AudioInputMusicGroup,
|
|
||||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
|
||||||
ChannelGroupIds.UserMusicInputGroup
|
|
||||||
],
|
|
||||||
usedMixers, sessionModel.getMixMode());
|
|
||||||
|
|
||||||
var oppositeMixers = _groupedMixersForClientId(
|
var myTrack = app.clientId == clientId;
|
||||||
clientId,
|
|
||||||
[
|
|
||||||
ChannelGroupIds.AudioInputMusicGroup,
|
|
||||||
ChannelGroupIds.PeerAudioInputMusicGroup,
|
|
||||||
ChannelGroupIds.UserMusicInputGroup
|
|
||||||
],
|
|
||||||
usedMixers, !sessionModel.getMixMode());
|
|
||||||
|
|
||||||
var mixer = null;
|
var mixerData = findMixerForTrack(clientId, track, myTrack)
|
||||||
var oppositeMixer = null;
|
|
||||||
if(currentMixers) {
|
var mixer = mixerData.mixer;
|
||||||
if(currentMixers[ChannelGroupIds.AudioInputMusicGroup]) {
|
var oppositeMixer = mixerData.oppositeMixer;
|
||||||
mixer = currentMixers[ChannelGroupIds.AudioInputMusicGroup][0]
|
var vuMixer = mixerData.vuMixer;
|
||||||
oppositeMixer = oppositeMixers[ChannelGroupIds.AudioInputMusicGroup][0]
|
var muteMixer = mixerData.muteMixer;
|
||||||
}
|
|
||||||
else if(sessionModel.isMasterMixMode() && currentMixers[ChannelGroupIds.PeerAudioInputMusicGroup]) {
|
if (mixer && oppositeMixer) {
|
||||||
mixer = currentMixers[ChannelGroupIds.PeerAudioInputMusicGroup][0]
|
var participant = (sessionModel.getParticipant(clientId) || {name:'unknown'}).name;
|
||||||
oppositeMixer = oppositeMixers[ChannelGroupIds.UserMusicInputGroup][0]
|
logger.debug("found mixer=" + mixer.id + ", participant=" + participant)
|
||||||
}
|
usedMixers[mixer.id] = true;
|
||||||
else if(!sessionModel.isMasterMixMode() && currentMixers[ChannelGroupIds.UserMusicInputGroup]) {
|
keysToDelete.push(data);
|
||||||
mixer = currentMixers[ChannelGroupIds.UserMusicInputGroup][0]
|
var gainPercent = percentFromMixerValue(
|
||||||
oppositeMixer = oppositeMixers[ChannelGroupIds.PeerAudioInputMusicGroup][0]
|
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) || { user: {name: 'unknown'}}).user.name;
|
||||||
var participant = (sessionModel.getParticipant(clientId) || {name:'unknown'}).name;
|
logger.debug("still looking for mixer for participant=" + participant + ", clientId=" + clientId)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i=0; i<keysToDelete.length; i++) {
|
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 > 20) {
|
||||||
lookingForMixersCount = 0;
|
lookingForMixersCount = 0;
|
||||||
lookingForMixers = {};
|
lookingForMixers = []
|
||||||
context.clearTimeout(lookingForMixersTimer);
|
context.clearTimeout(lookingForMixersTimer);
|
||||||
lookingForMixersTimer = null;
|
lookingForMixersTimer = null;
|
||||||
}
|
}
|
||||||
|
|
@ -1068,7 +1188,7 @@
|
||||||
|
|
||||||
// Given a mixerID and a value between 0.0-1.0,
|
// Given a mixerID and a value between 0.0-1.0,
|
||||||
// light up the proper VU lights.
|
// 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,
|
// Special-case for mono tracks. If mono, and it's a _vul id,
|
||||||
// update both sides, otherwise do nothing.
|
// update both sides, otherwise do nothing.
|
||||||
|
|
@ -1076,7 +1196,7 @@
|
||||||
var selector;
|
var selector;
|
||||||
var pureMixerId = mixerId.replace("_vul", "");
|
var pureMixerId = mixerId.replace("_vul", "");
|
||||||
pureMixerId = pureMixerId.replace("_vur", "");
|
pureMixerId = pureMixerId.replace("_vur", "");
|
||||||
var mixer = getMixer(pureMixerId, sessionModel.getMixMode());
|
var mixer = getMixer(pureMixerId);
|
||||||
if (mixer) {
|
if (mixer) {
|
||||||
if (!(mixer.stereo)) { // mono track
|
if (!(mixer.stereo)) { // mono track
|
||||||
if (mixerId.substr(-4) === "_vul") {
|
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 parentSelector = '#session-mytracks-container';
|
||||||
var $destination = $(parentSelector);
|
var $destination = $(parentSelector);
|
||||||
|
|
@ -1108,7 +1228,7 @@
|
||||||
var audioOverlay = $('.disabled-track-overlay', newTrack);
|
var audioOverlay = $('.disabled-track-overlay', newTrack);
|
||||||
var $trackIconMute = newTrack.find('.track-icon-mute')
|
var $trackIconMute = newTrack.find('.track-icon-mute')
|
||||||
$trackIconMute.muteSelector().on(EVENTS.MUTE_SELECTED, trackMuteSelected)
|
$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
|
audioOverlay.hide(); // always start with overlay hidden, and only show if no audio persists
|
||||||
$destination.append(newTrack);
|
$destination.append(newTrack);
|
||||||
|
|
@ -1116,7 +1236,7 @@
|
||||||
// Render VU meters and gain fader
|
// Render VU meters and gain fader
|
||||||
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
||||||
var gainPercent = trackData.gainPercent || 0;
|
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 + '"]');
|
var $closeButton = $('#div-track-close', 'div[track-id="' + trackData.trackId + '"]');
|
||||||
if (!allowDelete) {
|
if (!allowDelete) {
|
||||||
|
|
@ -1148,8 +1268,11 @@
|
||||||
// Render VU meters and gain fader
|
// Render VU meters and gain fader
|
||||||
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
||||||
var gainPercent = trackData.gainPercent || 0;
|
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);
|
tracks[trackData.trackId] = new context.JK.SessionTrack(trackData.clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1187,62 +1310,69 @@
|
||||||
//_toggleVisualMuteControl($muteControl, isMuted);
|
//_toggleVisualMuteControl($muteControl, isMuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBridgeCallback() {
|
function handleBridgeCallback(vuData) {
|
||||||
|
var j;
|
||||||
var eventName = null;
|
var eventName = null;
|
||||||
var mixerId = null;
|
var mixerId = null;
|
||||||
var value = null;
|
var value = null;
|
||||||
var tuples = arguments.length / 3;
|
var vuInfo = null;
|
||||||
for (var i=0; i<tuples; i++) {
|
for (j = 0; j < vuData.length; j++) {
|
||||||
eventName = arguments[3*i];
|
vuInfo = vuData[j];
|
||||||
mixerId = arguments[(3*i)+1];
|
var eventName = vuInfo[0];
|
||||||
value = arguments[(3*i)+2];
|
var vuVal = 0.0;
|
||||||
var vuVal = 0.0;
|
if(eventName === "vu") {
|
||||||
if (eventName === 'left_vu' || eventName === 'right_vu') {
|
var mixerId = vuInfo[1];
|
||||||
// TODO - no guarantee range will be -80 to 20. Get from the
|
var leftValue = vuInfo[2];
|
||||||
// GetControlState for this mixer which returns min/max
|
var leftClipping = vuInfo[3];
|
||||||
// value is a DB value from -80 to 20. Convert to float from 0.0-1.0
|
var rightValue = vuInfo[4];
|
||||||
vuVal = (value + 80) / 100;
|
var rightClipping = vuInfo[5];
|
||||||
if (eventName === 'left_vu') {
|
// TODO - no guarantee range will be -80 to 20. Get from the
|
||||||
mixerId = mixerId + "_vul";
|
// GetControlState for this mixer which returns min/max
|
||||||
} else {
|
// value is a DB value from -80 to 20. Convert to float from 0.0-1.0
|
||||||
mixerId = mixerId + "_vur";
|
_updateVU(mixerId + "_vul", (leftValue + 80) / 100, leftClipping);
|
||||||
}
|
_updateVU(mixerId + "_vur", (rightValue + 80) / 100, rightClipping);
|
||||||
_updateVU(mixerId, vuVal);
|
}
|
||||||
} else if (eventName === 'connection_status') {
|
else if(eventName === 'connection_status') {
|
||||||
// Connection Quality Change
|
var mixerId = vuInfo[1];
|
||||||
var connectionClass = 'green';
|
var value = vuInfo[2];
|
||||||
if (value < 7) {
|
|
||||||
connectionClass = 'yellow';
|
|
||||||
}
|
|
||||||
if (value < 4) {
|
|
||||||
connectionClass = 'red';
|
|
||||||
}
|
|
||||||
var clientId = _clientIdForUserInputMixer(mixerId, sessionModel.getMixMode());
|
|
||||||
|
|
||||||
if(clientId) {
|
// Connection Quality Change
|
||||||
var $connection = $('.session-track[client-id="' + clientId + '"] .track-connection');
|
var connectionClass = 'green';
|
||||||
if($connection.length == 0) {
|
if (value < 7) {
|
||||||
logger.debug("connection status: looking for clientId: " + clientId + ", mixer: " + mixerId)
|
connectionClass = 'yellow';
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
function deleteSession(evt) {
|
||||||
var sessionId = $(evt.currentTarget).attr("action-id");
|
var sessionId = $(evt.currentTarget).attr("action-id");
|
||||||
|
|
@ -1265,8 +1395,8 @@
|
||||||
sessionModel.deleteTrack(sessionId, trackId);
|
sessionModel.deleteTrack(sessionId, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _toggleVisualMuteControl($control, currentMixer, oppositeMixer) {
|
function _toggleVisualMuteControl($control, mute) {
|
||||||
if (currentMixer.mute) {
|
if (mute) {
|
||||||
$control.removeClass('enabled');
|
$control.removeClass('enabled');
|
||||||
$control.addClass('muted');
|
$control.addClass('muted');
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1275,10 +1405,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _toggleAudioMute(mixerId, muting) {
|
function _toggleAudioMute(mixerId, muting, mode) {
|
||||||
fillTrackVolumeObject(mixerId);
|
fillTrackVolumeObject(mixerId);
|
||||||
context.trackVolumeObject.mute = muting;
|
context.trackVolumeObject.mute = muting;
|
||||||
context.jamClient.SessionSetControlState(mixerId, sessionModel.getMixerMode());
|
|
||||||
|
if(mode === undefined) {
|
||||||
|
mode = sessionModel.getMixMode();
|
||||||
|
}
|
||||||
|
context.jamClient.SessionSetControlState(mixerId, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMuteDropdowns($control) {
|
function showMuteDropdowns($control) {
|
||||||
|
|
@ -1292,20 +1426,28 @@
|
||||||
|
|
||||||
// track icons have a special mute behavior
|
// track icons have a special mute behavior
|
||||||
if($control.is('.track-icon-mute')) {
|
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) {
|
var recordingDisabled = $control.data('recording-disabled');
|
||||||
_toggleVisualMuteControl($control, muting);
|
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 {
|
else {
|
||||||
$.each(mixerIds, function(i,v) {
|
$.each(mixerIds, function(i,v) {
|
||||||
|
|
@ -1319,29 +1461,23 @@
|
||||||
|
|
||||||
function fillTrackVolumeObject(mixerId, broadcast) {
|
function fillTrackVolumeObject(mixerId, broadcast) {
|
||||||
_updateMixers();
|
_updateMixers();
|
||||||
var mixer = null;
|
|
||||||
var _broadcast = true;
|
var _broadcast = true;
|
||||||
if (broadcast !== undefined) {
|
if (broadcast !== undefined) {
|
||||||
_broadcast = broadcast;
|
_broadcast = broadcast;
|
||||||
}
|
}
|
||||||
for (var i=0; i<mixers.length; i++) {
|
var mixer = getMixer(mixerId);
|
||||||
mixer = mixers[i];
|
context.trackVolumeObject.clientID = mixer.client_id;
|
||||||
if (mixer.id === mixerId) {
|
context.trackVolumeObject.broadcast = _broadcast;
|
||||||
context.trackVolumeObject.clientID = mixer.client_id;
|
context.trackVolumeObject.master = mixer.master;
|
||||||
context.trackVolumeObject.broadcast = _broadcast;
|
context.trackVolumeObject.monitor = mixer.monitor;
|
||||||
context.trackVolumeObject.master = mixer.master;
|
context.trackVolumeObject.mute = mixer.mute;
|
||||||
context.trackVolumeObject.monitor = mixer.monitor;
|
context.trackVolumeObject.name = mixer.name;
|
||||||
context.trackVolumeObject.mute = mixer.mute;
|
context.trackVolumeObject.record = mixer.record;
|
||||||
context.trackVolumeObject.name = mixer.name;
|
context.trackVolumeObject.volL = mixer.volume_left;
|
||||||
context.trackVolumeObject.record = mixer.record;
|
context.trackVolumeObject.volR = mixer.volume_right;
|
||||||
context.trackVolumeObject.volL = mixer.volume_left;
|
// trackVolumeObject doesn't have a place for range min/max
|
||||||
context.trackVolumeObject.volR = mixer.volume_right;
|
currentMixerRangeMin = mixer.range_low;
|
||||||
// trackVolumeObject doesn't have a place for range min/max
|
currentMixerRangeMax = mixer.range_high;
|
||||||
currentMixerRangeMin = mixer.range_low;
|
|
||||||
currentMixerRangeMax = mixer.range_high;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a mixer's min/max and current value, return it as
|
// Given a mixer's min/max and current value, return it as
|
||||||
|
|
@ -1394,7 +1530,7 @@
|
||||||
context.jamClient.SessionSetMasterLocalMix(dbValue);
|
context.jamClient.SessionSetMasterLocalMix(dbValue);
|
||||||
// context.jamClient.SessionSetMasterLocalMix(sliderValue);
|
// context.jamClient.SessionSetMasterLocalMix(sliderValue);
|
||||||
} else {
|
} else {
|
||||||
context.jamClient.SessionSetControlState(mixerId, sessionModel.getMixerMode());
|
context.jamClient.SessionSetControlState(mixerId, sessionModel.getMixMode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
var startTime = null;
|
var startTime = null;
|
||||||
var joinDeferred = null;
|
var joinDeferred = null;
|
||||||
|
|
||||||
var mixerMode = MIX_MODES.GLOBAL;
|
var mixerMode = MIX_MODES.PERSONAL;
|
||||||
|
|
||||||
server.registerOnSocketClosed(onWebsocketDisconnected);
|
server.registerOnSocketClosed(onWebsocketDisconnected);
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
// see if we already have tracks; if so, we need to run with these
|
// see if we already have tracks; if so, we need to run with these
|
||||||
var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
|
var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
|
||||||
if(inputTracks.length > 0) {
|
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);
|
sessionPageEnterDeferred.resolve(inputTracks);
|
||||||
var deferred = sessionPageEnterDeferred;
|
var deferred = sessionPageEnterDeferred;
|
||||||
sessionPageEnterDeferred = null;
|
sessionPageEnterDeferred = null;
|
||||||
|
|
@ -506,6 +506,10 @@
|
||||||
return mixerMode == MIX_MODES.MASTER;
|
return mixerMode == MIX_MODES.MASTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPersonalMixMode() {
|
||||||
|
return mixerMode == MIX_MODES.PERSONAL;
|
||||||
|
}
|
||||||
|
|
||||||
function getMixMode() {
|
function getMixMode() {
|
||||||
return mixerMode;
|
return mixerMode;
|
||||||
}
|
}
|
||||||
|
|
@ -668,6 +672,7 @@
|
||||||
this.inSession = inSession;
|
this.inSession = inSession;
|
||||||
this.setMixerMode = setMixerMode;
|
this.setMixerMode = setMixerMode;
|
||||||
this.isMasterMixMode = isMasterMixMode;
|
this.isMasterMixMode = isMasterMixMode;
|
||||||
|
this.isPersonalMixMode = isPersonalMixMode;
|
||||||
this.getMixMode = getMixMode;
|
this.getMixMode = getMixMode;
|
||||||
|
|
||||||
// ALERT HANDLERS
|
// ALERT HANDLERS
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,12 @@
|
||||||
|
|
||||||
localMusicTracks = context.JK.TrackHelpers.getTracks(jamClient, 2);
|
localMusicTracks = context.JK.TrackHelpers.getTracks(jamClient, 2);
|
||||||
|
|
||||||
console.log("getUserTracks", localMusicTracks)
|
|
||||||
var trackObjects = [];
|
var trackObjects = [];
|
||||||
|
|
||||||
for (i=0; i < localMusicTracks.length; i++) {
|
for (i=0; i < localMusicTracks.length; i++) {
|
||||||
var track = {};
|
var track = {};
|
||||||
track.client_track_id = localMusicTracks[i].id;
|
track.client_track_id = localMusicTracks[i].id;
|
||||||
|
track.client_resource_id = localMusicTracks[i].rid;
|
||||||
|
|
||||||
if(localMusicTracks[i].instrument_id === 0) {
|
if(localMusicTracks[i].instrument_id === 0) {
|
||||||
track.instrument_id = context.JK.server_to_client_instrument_map["Other"].server_id;
|
track.instrument_id = context.JK.server_to_client_instrument_map["Other"].server_id;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
*/
|
*/
|
||||||
renderVU: function(selector, userOptions) {
|
renderVU: function(selector, userOptions) {
|
||||||
selector = $(selector);
|
selector = $(selector);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default options for rendering a VU
|
* The default options for rendering a VU
|
||||||
*/
|
*/
|
||||||
|
|
@ -36,9 +38,13 @@
|
||||||
templateSelector = "#template-vu-h";
|
templateSelector = "#template-vu-h";
|
||||||
}
|
}
|
||||||
var templateSource = $(templateSelector).html();
|
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) {
|
updateVU: function ($selector, value) {
|
||||||
// There are 13 VU lights. Figure out how many to
|
// There are 13 VU lights. Figure out how many to
|
||||||
// light based on the incoming value.
|
// light based on the incoming value.
|
||||||
var countSelector = 'tr';
|
$selector.each(function() {
|
||||||
var horizontal = ($selector.find('table.horizontal').length);
|
var $track = $(this)
|
||||||
if (horizontal) {
|
var countSelector = 'tr';
|
||||||
countSelector = 'td';
|
var horizontal = ($track.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';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var lightIndex = horizontal ? i : lightCount - i - 1;
|
var lightCount = $track.find(countSelector).length;
|
||||||
allLightsSelector.eq(lightIndex).addClass(colorClass + state);
|
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[:connection_id],
|
||||||
params[:instrument_id],
|
params[:instrument_id],
|
||||||
params[:sound],
|
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)
|
respond_with @track, responder: ApiResponder, :status => 201, :location => api_session_track_detail_url(@track.connection.music_session, @track)
|
||||||
end
|
end
|
||||||
|
|
@ -384,7 +385,8 @@ class ApiMusicSessionsController < ApiController
|
||||||
nil,
|
nil,
|
||||||
params[:instrument_id],
|
params[:instrument_id],
|
||||||
params[:sound],
|
params[:sound],
|
||||||
params[:client_track_id])
|
params[:client_track_id],
|
||||||
|
params[:client_resource_id])
|
||||||
|
|
||||||
respond_with @track, responder: ApiResponder, :status => 200
|
respond_with @track, responder: ApiResponder, :status => 200
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,14 @@ else
|
||||||
|
|
||||||
child(:connections => :participants) {
|
child(:connections => :participants) {
|
||||||
collection @music_sessions, :object_root => false
|
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|
|
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 }
|
{ :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
|
end
|
||||||
|
|
||||||
child(:tracks => :tracks) {
|
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
|
end
|
||||||
|
|
||||||
child(:tracks => :tracks) {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,3 +163,11 @@
|
||||||
The files associated with this recording will be deleted as soon as your client has uploaded your tracks and stream mix from this recording.
|
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>
|
</div>
|
||||||
</script>
|
</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 -->
|
<!-- Track Template -->
|
||||||
<script type="text/template" id="template-session-track">
|
<script type="text/template" id="template-session-track">
|
||||||
<div track-id="{trackId}" class="session-track track" client-id="{clientId}">
|
<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-left" mixer-id="{vuMixerId}_vul"></div>
|
||||||
<div class="track-vu-right" mixer-id="{mixerId}_vur"></div>
|
<div class="track-vu-right" mixer-id="{vuMixerId}_vur"></div>
|
||||||
<div class="track-label">{name}</div>
|
<div class="track-label">{name}</div>
|
||||||
<div id="div-track-close" track-id="{trackId}" class="track-close op30">
|
<div id="div-track-close" track-id="{trackId}" class="track-close op30">
|
||||||
<%= image_tag "content/icon_closetrack.png", {:width => 12, :height => 12} %>
|
<%= image_tag "content/icon_closetrack.png", {:width => 12, :height => 12} %>
|
||||||
|
|
@ -173,7 +173,7 @@
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
<!-- TODO - connection class from curly param -->
|
<!-- TODO - connection class from curly param -->
|
||||||
<div mixer-id="{mixerId}_connection" class="track-connection grey">CONNECTION</div>
|
<div mixer-id="{mixerId}_connection" class="track-connection grey">CONNECTION</div>
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,7 @@ FactoryGirl.define do
|
||||||
factory :track, :class => JamRuby::Track do
|
factory :track, :class => JamRuby::Track do
|
||||||
sound "mono"
|
sound "mono"
|
||||||
sequence(:client_track_id) { |n| "client_track_id_seq_#{n}"}
|
sequence(:client_track_id) { |n| "client_track_id_seq_#{n}"}
|
||||||
|
sequence(:client_resource_id) { |n| "resource_id#{n}"}
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :video_source, :class => JamRuby::VideoSource do
|
factory :video_source, :class => JamRuby::VideoSource do
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue