Merge branch 'develop' into feature/vst
This commit is contained in:
commit
34dcc27641
|
|
@ -314,4 +314,5 @@ giftcard.sql
|
|||
add_description_to_crash_dumps.sql
|
||||
acappella.sql
|
||||
purchasable_gift_cards.sql
|
||||
versionable_jamtracks.sql
|
||||
versionable_jamtracks.sql
|
||||
session_controller.sql
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE music_sessions ADD COLUMN session_controller_id VARCHAR(64) REFERENCES users(id);
|
||||
|
|
@ -28,13 +28,13 @@ module JamRuby
|
|||
|
||||
##### TODO: refactored to notification.rb but left here for backwards compatibility w/ connection_manager_spec.rb
|
||||
def gather_friends(connection, user_id)
|
||||
friend_ids = []
|
||||
connection.exec("SELECT f1.friend_id as friend_id FROM friendships f1 WHERE f1.user_id = $1 AND f1.friend_id IN (SELECT f2.user_id FROM friendships f2 WHERE f2.friend_id = $1)", [user_id]) do |friend_results|
|
||||
friend_results.each do |friend_result|
|
||||
friend_ids.push(friend_result['friend_id'])
|
||||
end
|
||||
friend_ids = []
|
||||
connection.exec("SELECT f1.friend_id as friend_id FROM friendships f1 WHERE f1.user_id = $1 AND f1.friend_id IN (SELECT f2.user_id FROM friendships f2 WHERE f2.friend_id = $1)", [user_id]) do |friend_results|
|
||||
friend_results.each do |friend_result|
|
||||
friend_ids.push(friend_result['friend_id'])
|
||||
end
|
||||
return friend_ids
|
||||
end
|
||||
return friend_ids
|
||||
end
|
||||
|
||||
# this simulates music_session destroy callbacks with activerecord
|
||||
|
|
@ -42,7 +42,7 @@ module JamRuby
|
|||
music_session = ActiveMusicSession.find_by_id(music_session_id)
|
||||
music_session.before_destroy if music_session
|
||||
end
|
||||
|
||||
|
||||
# reclaim the existing connection, if ip_address is not nil then perhaps a new address as well
|
||||
def reconnect(conn, channel_id, reconnect_music_session_id, ip_address, connection_stale_time, connection_expire_time, udp_reachable, gateway)
|
||||
music_session_id = nil
|
||||
|
|
@ -65,11 +65,19 @@ module JamRuby
|
|||
|
||||
isp = JamIsp.lookup(addr)
|
||||
#puts("============= JamIsp.lookup returns #{isp.inspect} for #{addr} =============")
|
||||
if isp.nil? then ispid = 0 else ispid = isp.coid end
|
||||
if isp.nil? then
|
||||
ispid = 0
|
||||
else
|
||||
ispid = isp.coid
|
||||
end
|
||||
|
||||
block = GeoIpBlocks.lookup(addr)
|
||||
#puts("============= GeoIpBlocks.lookup returns #{block.inspect} for #{addr} =============")
|
||||
if block.nil? then locid = 0 else locid = block.locid end
|
||||
if block.nil? then
|
||||
locid = 0
|
||||
else
|
||||
locid = block.locid
|
||||
end
|
||||
|
||||
location = GeoIpLocations.find_by_locid(locid)
|
||||
if location.nil? || isp.nil? || block.nil?
|
||||
|
|
@ -183,11 +191,19 @@ SQL
|
|||
|
||||
isp = JamIsp.lookup(addr)
|
||||
#puts("============= JamIsp.lookup returns #{isp.inspect} for #{addr} =============")
|
||||
if isp.nil? then ispid = 0 else ispid = isp.coid end
|
||||
if isp.nil? then
|
||||
ispid = 0
|
||||
else
|
||||
ispid = isp.coid
|
||||
end
|
||||
|
||||
block = GeoIpBlocks.lookup(addr)
|
||||
#puts("============= GeoIpBlocks.lookup returns #{block.inspect} for #{addr} =============")
|
||||
if block.nil? then locid = 0 else locid = block.locid end
|
||||
if block.nil? then
|
||||
locid = 0
|
||||
else
|
||||
locid = block.locid
|
||||
end
|
||||
|
||||
location = GeoIpLocations.find_by_locid(locid)
|
||||
if location.nil? || isp.nil? || block.nil?
|
||||
|
|
@ -199,11 +215,11 @@ SQL
|
|||
lock_connections(conn)
|
||||
|
||||
conn.exec("INSERT INTO connections (user_id, client_id, channel_id, ip_address, client_type, addr, locidispid, aasm_state, stale_time, expire_time, udp_reachable, gateway) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
|
||||
[user_id, client_id, channel_id, ip_address, client_type, addr, locidispid, Connection::CONNECT_STATE.to_s, connection_stale_time, connection_expire_time, udp_reachable, gateway]).clear
|
||||
[user_id, client_id, channel_id, ip_address, client_type, addr, locidispid, Connection::CONNECT_STATE.to_s, connection_stale_time, connection_expire_time, udp_reachable, gateway]).clear
|
||||
|
||||
# we just created a new connection-if this is the first time the user has shown up, we need to send out a message to his friends
|
||||
conn.exec("SELECT count(user_id) FROM connections WHERE user_id = $1", [user_id]) do |result|
|
||||
count = result.getvalue(0, 0) .to_i
|
||||
count = result.getvalue(0, 0).to_i
|
||||
# we're passing all this stuff so that the user record might be updated as well...
|
||||
blk.call(conn, count) unless blk.nil?
|
||||
end
|
||||
|
|
@ -291,7 +307,7 @@ SQL
|
|||
|
||||
# destroy the music_session if it's empty
|
||||
num_participants = nil
|
||||
conn.exec("SELECT count(*) FROM connections WHERE music_session_id = $1",
|
||||
conn.exec("SELECT count(*) FROM connections WHERE music_session_id = $1",
|
||||
[previous_music_session_id]) do |result|
|
||||
num_participants = result.getvalue(0, 0).to_i
|
||||
end
|
||||
|
|
@ -324,11 +340,65 @@ SQL
|
|||
|
||||
conn.exec("UPDATE active_music_sessions set jam_track_id = NULL, jam_track_initiator_id = NULL where jam_track_initiator_id = $1 and id = $2",
|
||||
[user_id, previous_music_session_id])
|
||||
|
||||
update_session_controller(previous_music_session_id)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def update_session_controller(music_session_id)
|
||||
active_music_session = ActiveMusicSession.find(music_session_id)
|
||||
|
||||
if active_music_session
|
||||
music_session = active_music_session.music_session
|
||||
if music_session.session_controller_id && !active_music_session.users.exists?(music_session.session_controller)
|
||||
# find next in line, because the current 'session controller' is not part of the session
|
||||
next_in_line(music_session, active_music_session)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# determine who should be session controller after someone leaves
|
||||
def next_in_line(music_session, active_music_session)
|
||||
session_users = active_music_session.users
|
||||
|
||||
# check friends 1st
|
||||
session_friends = music_session.creator.friends && session_users
|
||||
if session_friends.length > 0
|
||||
music_session.session_controller = session_friends[0]
|
||||
if music_session.save
|
||||
active_music_session.tick_track_changes
|
||||
Notification.send_tracks_changed(active_music_session)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# check invited 2nd
|
||||
invited = music_session.invited_musicians && session_users
|
||||
if invited.length > 0
|
||||
music_session.session_controller = invited[0]
|
||||
if music_session.save
|
||||
active_music_session.tick_track_changes
|
||||
Notification.send_tracks_changed(active_music_session)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# go by who joined earliest
|
||||
earliest = active_music_sessions.connections.order(:joined_session_at).first
|
||||
|
||||
if earliest
|
||||
music_session.session_controller = earliest
|
||||
if music_session.save
|
||||
active_music_session.tick_track_changes
|
||||
Notification.send_tracks_changed(active_music_session)
|
||||
return
|
||||
end
|
||||
end
|
||||
music_session.creator
|
||||
end
|
||||
|
||||
def join_music_session(user, client_id, music_session, as_musician, tracks, audio_latency, video_sources=nil)
|
||||
connection = nil
|
||||
|
||||
|
|
@ -349,7 +419,10 @@ SQL
|
|||
|
||||
if connection.errors.any?
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
update_session_controller(music_session.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
connection
|
||||
|
|
@ -383,6 +456,8 @@ SQL
|
|||
if result.cmd_tuples == 1
|
||||
@log.debug("disassociated music_session with connection for client_id=#{client_id}, user_id=#{user_id}")
|
||||
|
||||
update_session_controller(music_session.id)
|
||||
|
||||
JamRuby::MusicSessionUserHistory.removed_music_session(user_id, music_session_id)
|
||||
session_checks(conn, previous_music_session_id, user_id)
|
||||
blk.call() unless blk.nil?
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ module JamRuby
|
|||
|
||||
belongs_to :active_music_session, :class_name => 'JamRuby::ActiveMusicSession', foreign_key: :music_session_id
|
||||
|
||||
belongs_to :session_controller, :class_name => 'JamRuby::User', :foreign_key => :session_controller_id, :inverse_of => :controlled_sessions
|
||||
|
||||
has_many :music_session_user_histories, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id", :dependent => :delete_all
|
||||
has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id"
|
||||
has_many :session_info_comments, :class_name => "JamRuby::SessionInfoComment", :foreign_key => "music_session_id"
|
||||
|
|
@ -116,6 +118,7 @@ module JamRuby
|
|||
new_session.open_rsvps = self.open_rsvps
|
||||
new_session.is_unstructured_rsvp = self.is_unstructured_rsvp
|
||||
new_session.legal_terms = true
|
||||
new_session.session_controller = self.session_controller
|
||||
|
||||
# copy rsvp_slots, rsvp_requests, and rsvp_requests_rsvp_slots
|
||||
RsvpSlot.find_each(:conditions => "music_session_id = '#{self.id}'") do |slot|
|
||||
|
|
@ -255,6 +258,30 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def set_session_controller(current_user, user)
|
||||
|
||||
# only allow update of session controller by the creator or the currently marked user
|
||||
|
||||
should_tick = false
|
||||
|
||||
if current_user != creator && current_user != self.session_controller
|
||||
return should_tick
|
||||
end
|
||||
|
||||
if active_music_session
|
||||
if user
|
||||
if active_music_session.users.exists?(user)
|
||||
self.session_controller = user
|
||||
should_tick = save
|
||||
end
|
||||
else
|
||||
self.session_controller = nil
|
||||
should_tick = save
|
||||
end
|
||||
end
|
||||
should_tick
|
||||
end
|
||||
|
||||
def self.index(current_user, user_id, band_id = nil, genre = nil)
|
||||
hide_private = false
|
||||
if current_user.id != user_id
|
||||
|
|
@ -343,6 +370,7 @@ module JamRuby
|
|||
ms.legal_terms = true
|
||||
ms.open_rsvps = options[:open_rsvps] if options[:open_rsvps]
|
||||
ms.creator = user
|
||||
ms.session_controller = user
|
||||
ms.create_type = options[:create_type]
|
||||
ms.is_unstructured_rsvp = options[:isUnstructuredRsvp] if options[:isUnstructuredRsvp]
|
||||
ms.scheduled_start = parse_scheduled_start(options[:start], options[:timezone]) if options[:start] && options[:timezone]
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ module JamRuby
|
|||
|
||||
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
|
||||
|
||||
has_many :controlled_sessions, :class_name=> "JamRuby::MusicSession", inverse_of: :session_controller, foreign_key: :session_controller_id
|
||||
|
||||
# authorizations (for facebook, etc -- omniauth)
|
||||
has_many :user_authorizations, :class_name => "JamRuby::UserAuthorization"
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,20 @@
|
|||
$('#session-settings-fan-access').val('listen-chat-band');
|
||||
}
|
||||
|
||||
var $controllerSelect = $('#session-settings-master-mix-controller')
|
||||
|
||||
$controllerSelect.empty()
|
||||
var sessionUsers = context.SessionStore.helper.users()
|
||||
|
||||
$controllerSelect.append('<option value="">Any one can control the Master Mix</option>')
|
||||
$.each(sessionUsers, function(userId, user) {
|
||||
var selected = currentSession.session_controller_id == userId ? 'selected="selected"' : ''
|
||||
$controllerSelect.append('<option value="' + userId + '"' + selected + '>' + user.name +'</option>')
|
||||
})
|
||||
|
||||
var canEditController = currentSession.session_controller_id == context.JK.currentUserId || context.JK.currentUserId == currentSession.user_id
|
||||
$controllerSelect.easyDropDown(canEditController ? 'enable' : 'disable')
|
||||
|
||||
/**
|
||||
// notation files in the account screen. ugh.
|
||||
$selectedFilenames.empty();
|
||||
|
|
@ -84,10 +98,12 @@
|
|||
context.JK.dropdown($('#session-settings-language'));
|
||||
context.JK.dropdown($('#session-settings-musician-access'));
|
||||
context.JK.dropdown($('#session-settings-fan-access'));
|
||||
context.JK.dropdown($('#session-settings-master-mix-controller'));
|
||||
|
||||
var easyDropDownState = canPlayWithOthers.canPlay ? 'enable' : 'disable'
|
||||
$('#session-settings-musician-access').easyDropDown(easyDropDownState)
|
||||
$('#session-settings-fan-access').easyDropDown(easyDropDownState)
|
||||
|
||||
}
|
||||
|
||||
function addNotation(notation) {
|
||||
|
|
@ -121,6 +137,7 @@
|
|||
data.name = $('#session-settings-name').val();
|
||||
data.description = $('#session-settings-description').val();
|
||||
data.language = $('#session-settings-language').val();
|
||||
data.session_controller = $('#session-settings-master-mix-controller').val()
|
||||
|
||||
// musician access
|
||||
var musicianAccess = $('#session-settings-musician-access').val();
|
||||
|
|
@ -148,7 +165,13 @@
|
|||
data.fan_chat = true;
|
||||
}
|
||||
|
||||
rest.updateSession($('#session-settings-id').val(), data).done(settingsSaved);
|
||||
rest.updateSession($('#session-settings-id').val(), data).done(settingsSaved)
|
||||
.done(function(response) {
|
||||
context.SessionActions.updateSession.trigger(response);
|
||||
})
|
||||
.fail(function() {
|
||||
app.notify({title: "Can't Update", text: "Unable to update session settings."})
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,14 @@
|
|||
var $fader = $(this);
|
||||
var floaterConvert = $fader.data('floaterConverter')
|
||||
var sessionModel = window.JK.CurrentSessionModel || null;
|
||||
|
||||
|
||||
/**
|
||||
if(!$fader.data('has-session-control')) {
|
||||
var sessionControllerName = $fader.data('session-controller-name');
|
||||
window.JK.prodBubble($fader, 'not-session-controller', {sessionControllerName:sessionControllerName}, {positions:['left', 'right'], offsetParent: $fader.closest('.top-parent'), duration:12000})
|
||||
return false;
|
||||
}*/
|
||||
|
||||
var mediaControlsDisabled = $fader.data('media-controls-disabled');
|
||||
if(mediaControlsDisabled) {
|
||||
var mediaTrackOpener = $fader.data('media-track-opener');
|
||||
|
|
@ -173,7 +180,14 @@
|
|||
var mediaControlsDisabled = $draggingFaderHandle.data('media-controls-disabled');
|
||||
var mediaTrackOpener = $draggingFaderHandle.data('media-track-opener');
|
||||
var sessionModel = window.JK.CurrentSessionModel || null;
|
||||
|
||||
|
||||
/**
|
||||
if(!$draggingFaderHandle.data('has-session-control')) {
|
||||
var sessionControllerName = $draggingFaderHandle.data('session-controller-name');
|
||||
window.JK.prodBubble($draggingFaderHandle, 'not-session-controller', {sessionControllerName:sessionControllerName}, {positions:['left', 'right'], offsetParent: $draggingFaderHandle.closest('.top-parent'), duration:12000})
|
||||
return false;
|
||||
}*/
|
||||
|
||||
if(mediaControlsDisabled) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -267,16 +281,33 @@
|
|||
throw ("renderFader: userOptions is required");
|
||||
}
|
||||
var renderDefaults = {
|
||||
faderType: "vertical"
|
||||
faderType: "vertical",
|
||||
sessionController: null
|
||||
};
|
||||
var options = $.extend({}, renderDefaults, userOptions);
|
||||
|
||||
var sessionCanControl = true
|
||||
var sessionControllerName = null
|
||||
if(userOptions.sessionController) {
|
||||
if(!userOptions.sessionController.can_control) {
|
||||
sessionCanControl = false
|
||||
sessionControllerName = userOptions.sessionController.session_controller.name
|
||||
}
|
||||
}
|
||||
|
||||
selector.find('div[data-control="fader"]')
|
||||
.data('media-controls-disabled', selector.data('media-controls-disabled'))
|
||||
.data('media-track-opener', selector.data('media-track-opener'))
|
||||
.data('showHelpAboutMediaMixers', selector.data('showHelpAboutMediaMixers'))
|
||||
.data('floaterConverter', floaterConverter)
|
||||
.data('snap', userOptions.snap)
|
||||
.data('has-session-control', sessionCanControl)
|
||||
.data('session-controller-name', sessionControllerName)
|
||||
|
||||
|
||||
if(userOptions.sessionController) {
|
||||
|
||||
}
|
||||
|
||||
selector.find('div[data-control="fader-handle"]').draggable({
|
||||
drag: onFaderDrag,
|
||||
|
|
@ -289,6 +320,8 @@
|
|||
.data('showHelpAboutMediaMixers', selector.data('showHelpAboutMediaMixers'))
|
||||
.data('floaterConverter', floaterConverter)
|
||||
.data('snap', userOptions.snap)
|
||||
.data('has-session-control', sessionCanControl)
|
||||
.data('session-controller-name', sessionControllerName)
|
||||
|
||||
// Embed any custom styles, applied to the .fader below selector
|
||||
if ("style" in options) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,17 @@ context = window
|
|||
|
||||
openDialog: (e) ->
|
||||
e.preventDefault()
|
||||
context.JK.app.layout.showDialog('session-master-mix-dialog')
|
||||
|
||||
sessionController = context.SessionStore.helper.sessionController()
|
||||
|
||||
# does this user have access to control the master mixer?
|
||||
|
||||
if sessionController.can_control
|
||||
context.JK.app.layout.showDialog('session-master-mix-dialog')
|
||||
else
|
||||
sessionControllerName = sessionController.session_controller?.name
|
||||
$node = $(this.getDOMNode())
|
||||
window.JK.prodBubble($node, 'not-session-controller', {sessionControllerName:sessionControllerName}, {positions:['bottom'], offsetParent: $node.closest('.top-parent'), duration:12000})
|
||||
|
||||
render: () ->
|
||||
`<a className="session-mixer button-grey left" onClick={this.openDialog}>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ context = window
|
|||
logger = context.JK.logger
|
||||
ChannelGroupIds = context.JK.ChannelGroupIds
|
||||
CategoryGroupIds = context.JK.CategoryGroupIds
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
|
||||
@SessionTrackGain = React.createClass({
|
||||
|
||||
|
|
@ -20,6 +21,8 @@ CategoryGroupIds = context.JK.CategoryGroupIds
|
|||
groupId = $target.data('groupId')
|
||||
mixers = @state.mixers.mixer
|
||||
|
||||
|
||||
|
||||
# if this is a media track, jam track , or media category, affect volume of both mixer and opposing mixer
|
||||
if @state.mixers.mixer.group_id == ChannelGroupIds.MediaTrackGroup || @state.mixers.mixer.group_id == ChannelGroupIds.JamTrackGroup || ((@state.mixers.mixer.group_id == ChannelGroupIds.MonitorCatGroup || @state.mixers.mixer.group_id == ChannelGroupIds.MasterCatGroup) && @state.mixers.mixer.name == CategoryGroupIds.MediaTrack)
|
||||
MixerActions.faderChanged(data, [@state.mixers.mixer, @state.mixers.oppositeMixer], @props.gainType)
|
||||
|
|
@ -47,13 +50,18 @@ CategoryGroupIds = context.JK.CategoryGroupIds
|
|||
if !$root.is('.track-gain')
|
||||
logger.error("unknown root node")
|
||||
|
||||
context.JK.FaderHelpers.renderFader2($root, {faderType: 'vertical'});
|
||||
|
||||
# Initialize gain position
|
||||
mixer = @state.mixers?.mixer
|
||||
if mixer && $.isArray(mixer)
|
||||
mixer = mixer[0]
|
||||
|
||||
sessionController = null
|
||||
if mixer.mode == MIX_MODES.MASTER
|
||||
# sessionController is only relevant for master mode
|
||||
sessionController = this.props.sessionController
|
||||
|
||||
context.JK.FaderHelpers.renderFader2($root, {faderType: 'vertical', sessionController:sessionController});
|
||||
|
||||
MixerActions.initGain(mixer)
|
||||
|
||||
# watch for fader change events
|
||||
|
|
|
|||
|
|
@ -24,10 +24,13 @@ ptrCount = 0
|
|||
newMixers = mixers.refreshMixer(@state.mixers)
|
||||
|
||||
newMixers = {} unless newMixers?
|
||||
this.setState({mixers: newMixers})
|
||||
sessionController = sessionMixers.session.sessionController()
|
||||
logger.debug("session controller", sessionController)
|
||||
|
||||
this.setState({mixers: newMixers, sessionController: sessionController})
|
||||
|
||||
getInitialState: () ->
|
||||
{mixers: this.props.mixers, ptr: "STVH#{ptrCount++}" }
|
||||
{mixers: this.props.mixers, ptr: "STVH#{ptrCount++}", sessionController: window.SessionStore.helper.sessionController()}
|
||||
|
||||
handleMute: (e) ->
|
||||
e.preventDefault()
|
||||
|
|
@ -85,7 +88,7 @@ ptrCount = 0
|
|||
<div>Volume</div>
|
||||
<div>{volume_left}dB</div>
|
||||
</div>
|
||||
<SessionTrackGain mixers={this.state.mixers} gainType={this.props.gainType} />
|
||||
<SessionTrackGain mixers={this.state.mixers} gainType={this.props.gainType} sessionController={this.state.sessionController} />
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
|
||||
<input type="checkbox" name="mute"/>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@ context = window
|
|||
else
|
||||
[]
|
||||
|
||||
users: () ->
|
||||
found = {}
|
||||
|
||||
for participant in @participants()
|
||||
found[participant.user.id] = participant.user
|
||||
|
||||
found
|
||||
|
||||
otherParticipants: () ->
|
||||
others = []
|
||||
for participant in @participants()
|
||||
|
|
@ -26,6 +34,26 @@ context = window
|
|||
others.push(participant) unless myTrack
|
||||
others
|
||||
|
||||
sessionController: () ->
|
||||
info = {}
|
||||
|
||||
# XXX testing:
|
||||
info["can_control"] = false
|
||||
info["session_controller"] = @participants()[0].user
|
||||
|
||||
if @session
|
||||
if @session.session_controller_id == null
|
||||
info['session_controller'] = null
|
||||
info['can_control'] = true
|
||||
else
|
||||
for participant in @participants()
|
||||
if participant.user.id == @session.session_controller_id
|
||||
info['session_controller'] = participant.user
|
||||
info['can_control'] = participant.user.id == context.JK.currentUserId
|
||||
break
|
||||
|
||||
info
|
||||
|
||||
# if any participant has the metronome open, then we say this session has the metronome open
|
||||
isMetronomeOpen: () ->
|
||||
@session? && @session.metronome_active
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ body.jam, body.web, .dialog{
|
|||
}
|
||||
}
|
||||
|
||||
.larger-text {
|
||||
margin:10px;
|
||||
font-size:12px;
|
||||
line-height:125%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ class ApiMusicSessionsController < ApiController
|
|||
end
|
||||
|
||||
def update
|
||||
@music_session = MusicSessionManager.new.update(
|
||||
@music_session = MusicSessionManager.new.update(current_user,
|
||||
@music_session.music_session,
|
||||
params[:name],
|
||||
params[:description],
|
||||
|
|
@ -180,14 +180,16 @@ class ApiMusicSessionsController < ApiController
|
|||
params[:musician_access],
|
||||
params[:approval_required],
|
||||
params[:fan_chat],
|
||||
params[:fan_access])
|
||||
params[:fan_access],
|
||||
params[:session_controller])
|
||||
|
||||
if @music_session.errors.any?
|
||||
# we have to do this because api_session_detail_url will fail with a bad @music_session
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @music_session
|
||||
else
|
||||
respond_with @music_session, responder: ApiResponder, :location => api_session_detail_url(@music_session)
|
||||
@music_session = @music_session.active_music_session
|
||||
respond_with_model(@music_session)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -573,7 +575,6 @@ class ApiMusicSessionsController < ApiController
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
def jam_track_open
|
||||
unless @music_session.users.exists?(current_user)
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @music_session
|
||||
|
||||
extends "api_music_sessions/show"
|
||||
|
|
@ -37,12 +37,17 @@ else
|
|||
end
|
||||
end
|
||||
|
||||
node :share_url do |music_session|
|
||||
node do |music_session|
|
||||
session_props = {}
|
||||
unless music_session.music_session.share_token.nil?
|
||||
share_token_url(music_session.music_session.share_token.token)
|
||||
session_props[:share_url] = share_token_url(music_session.music_session.share_token.token)
|
||||
end
|
||||
|
||||
session_props[:session_controller_id] = music_session.music_session.session_controller_id
|
||||
session_props
|
||||
end
|
||||
|
||||
|
||||
child(:connections => :participants) {
|
||||
collection @music_sessions, :object_root => false
|
||||
attributes :ip_address, :client_id, :joined_session_at, :audio_latency, :id, :metronome_open
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @music_session
|
||||
|
||||
extends "api_music_sessions/show"
|
||||
|
|
@ -222,6 +222,16 @@ script type="text/template" id="template-help-media-controls-disabled"
|
|||
| Only the person who opened the recording can control the volume levels.
|
||||
| {% } %}
|
||||
|
||||
|
||||
script type="text/template" id="template-help-not-session-controller"
|
||||
.not-session-controller.larger-text
|
||||
| This feature controls the master mix for the session, which is used to set the mix levels for recordings and session broadcasts,
|
||||
| so changes to the master mix affect all musicians in the session.
|
||||
| Only {{data.sessionControllerName}} has control of the master mix for this session.
|
||||
br
|
||||
br
|
||||
| If you want to change the personal mix – i.e. the mix/levels that you personally hear – you can use the volume sliders on each track on the session screen to do this, and it won’t affect what other musicians in the session hear, so you can do this safely.
|
||||
|
||||
script type="text/template" id="template-help-jamtrack-controls-disabled"
|
||||
| During a recording, volume and mute controls for JamTracks are disabled. So, get the session volume levels right before starting the recording.
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@
|
|||
%option{:value => "#{language[:id]}"}
|
||||
= language[:label]
|
||||
|
||||
.clearall.left.w20.ib.mb10
|
||||
Mix Controller:
|
||||
.right.w75.ib.mb10
|
||||
%select{:name => "master_mix_controller", :id => "session-settings-master-mix-controller"}
|
||||
|
||||
.clearall.left.w20.ib.mb10
|
||||
Musician Access:
|
||||
.right.w75.ib.mb10
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/sessions/:id/backing_tracks/close' => 'api_music_sessions#backing_track_close', :via => :post
|
||||
match '/sessions/:id/metronome/open' => 'api_music_sessions#metronome_open', :via => :post
|
||||
match '/sessions/:id/metronome/close' => 'api_music_sessions#metronome_close', :via => :post
|
||||
match '/sessions/:id/session_controller' => 'api_music_sessions#session_controller', :via => :post
|
||||
|
||||
# music session tracks
|
||||
match '/sessions/:id/tracks' => 'api_music_sessions#track_create', :via => :post
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class MusicSessionManager < BaseManager
|
|||
end
|
||||
|
||||
# Update the session. If a field is left out (meaning, it's set to nil), it's not updated.
|
||||
def update(music_session, name, description, genre, language, musician_access, approval_required, fan_chat, fan_access)
|
||||
def update(current_user, music_session, name, description, genre, language, musician_access, approval_required, fan_chat, fan_access, session_controller_id)
|
||||
|
||||
music_session.name = name unless name.nil?
|
||||
music_session.description = description unless description.nil?
|
||||
|
|
@ -77,7 +77,15 @@ class MusicSessionManager < BaseManager
|
|||
music_session.approval_required = approval_required unless approval_required.nil?
|
||||
music_session.fan_chat = fan_chat unless fan_chat.nil?
|
||||
music_session.fan_access = fan_access unless fan_access.nil?
|
||||
session_controller = User.find(session_controller_id) if session_controller_id.present?
|
||||
should_tick = music_session.set_session_controller(current_user, session_controller)
|
||||
music_session.save
|
||||
|
||||
if should_tick && music_session.active_music_session
|
||||
music_session.active_music_session.tick_track_changes
|
||||
Notification.send_tracks_changed(music_session.active_music_session)
|
||||
end
|
||||
|
||||
music_session
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue