diff --git a/web/app/assets/javascripts/react-components/SessionTrackGain.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionTrackGain.js.jsx.coffee
index c4d1c6123..000d176c7 100644
--- a/web/app/assets/javascripts/react-components/SessionTrackGain.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionTrackGain.js.jsx.coffee
@@ -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
diff --git a/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee
index fe0eba212..8d41f2017 100644
--- a/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionTrackVolumeHover.js.jsx.coffee
@@ -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
Volume
{volume_left}dB
-
+
diff --git a/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee b/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee
index 460aa98e8..50a129972 100644
--- a/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee
+++ b/web/app/assets/javascripts/react-components/helpers/SessionHelper.js.coffee
@@ -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
diff --git a/web/app/assets/stylesheets/client/help.css.scss b/web/app/assets/stylesheets/client/help.css.scss
index 7082d7d27..2e7ca51d6 100644
--- a/web/app/assets/stylesheets/client/help.css.scss
+++ b/web/app/assets/stylesheets/client/help.css.scss
@@ -60,6 +60,11 @@ body.jam, body.web, .dialog{
}
}
+ .larger-text {
+ margin:10px;
+ font-size:12px;
+ line-height:125%;
+ }
diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb
index c7433ea5a..9fcb0bf7b 100644
--- a/web/app/controllers/api_music_sessions_controller.rb
+++ b/web/app/controllers/api_music_sessions_controller.rb
@@ -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
diff --git a/web/app/views/api_music_sessions/session_controller.rabl b/web/app/views/api_music_sessions/session_controller.rabl
new file mode 100644
index 000000000..e34b6943d
--- /dev/null
+++ b/web/app/views/api_music_sessions/session_controller.rabl
@@ -0,0 +1,3 @@
+object @music_session
+
+extends "api_music_sessions/show"
\ No newline at end of file
diff --git a/web/app/views/api_music_sessions/show.rabl b/web/app/views/api_music_sessions/show.rabl
index 39a71810c..61067a716 100644
--- a/web/app/views/api_music_sessions/show.rabl
+++ b/web/app/views/api_music_sessions/show.rabl
@@ -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
diff --git a/web/app/views/api_music_sessions/update.rabl b/web/app/views/api_music_sessions/update.rabl
new file mode 100644
index 000000000..e34b6943d
--- /dev/null
+++ b/web/app/views/api_music_sessions/update.rabl
@@ -0,0 +1,3 @@
+object @music_session
+
+extends "api_music_sessions/show"
\ No newline at end of file
diff --git a/web/app/views/clients/_help.html.slim b/web/app/views/clients/_help.html.slim
index ba3dc8ceb..d5bef7834 100644
--- a/web/app/views/clients/_help.html.slim
+++ b/web/app/views/clients/_help.html.slim
@@ -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.
diff --git a/web/app/views/clients/_sessionSettings.html.haml b/web/app/views/clients/_sessionSettings.html.haml
index abd85514e..7aeaf5dd0 100644
--- a/web/app/views/clients/_sessionSettings.html.haml
+++ b/web/app/views/clients/_sessionSettings.html.haml
@@ -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
diff --git a/web/config/routes.rb b/web/config/routes.rb
index cb96586fe..48755c292 100644
--- a/web/config/routes.rb
+++ b/web/config/routes.rb
@@ -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
diff --git a/web/lib/music_session_manager.rb b/web/lib/music_session_manager.rb
index 792fe1200..81b52db49 100644
--- a/web/lib/music_session_manager.rb
+++ b/web/lib/music_session_manager.rb
@@ -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