* fix bugs
This commit is contained in:
parent
3538e7b0ae
commit
b107df2478
|
|
@ -7,7 +7,7 @@ module JamRuby
|
|||
|
||||
belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track
|
||||
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
|
||||
has_many :jam_track_mixdown_packages, class_name: "JamRuby::JamTrackMixdownPackage"
|
||||
has_many :jam_track_mixdown_packages, class_name: "JamRuby::JamTrackMixdownPackage", order: 'created_at DESC'
|
||||
has_one :jam_track_right, class_name: 'JamRuby::JamTrackRight', foreign_key: 'last_mixdown_id', inverse_of: :last_mixdown
|
||||
|
||||
validates :name, presence: true, length: {maximum: 100}
|
||||
|
|
@ -19,6 +19,7 @@ module JamRuby
|
|||
validates_uniqueness_of :name, scope: :user_id
|
||||
|
||||
validate :verify_settings
|
||||
validate :verify_max_mixdowns
|
||||
|
||||
def self.index(params, user)
|
||||
jam_track_id = params[:id]
|
||||
|
|
@ -38,11 +39,19 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def verify_max_mixdowns
|
||||
if self.jam_track && self.user && self.jam_track.mixdowns_for_user(self.user).length >= 5
|
||||
errors.add(:jam_track, 'allowed 5 mixes')
|
||||
end
|
||||
end
|
||||
|
||||
def verify_settings
|
||||
|
||||
# the user has to specify at least at least one tweak to volume, speed, pitch, pan. otherwise there is nothing to do
|
||||
|
||||
tweaked = false
|
||||
all_quiet = true
|
||||
|
||||
parsed = JSON.parse(self.settings)
|
||||
if parsed["speed"]
|
||||
tweaked = true
|
||||
|
|
@ -50,6 +59,8 @@ module JamRuby
|
|||
if parsed["pitch"]
|
||||
tweaked = true
|
||||
end
|
||||
|
||||
|
||||
if parsed["tracks"]
|
||||
parsed["tracks"].each do |track|
|
||||
if track["mute"]
|
||||
|
|
@ -61,8 +72,17 @@ module JamRuby
|
|||
if track["pan"] && track["pan"] != 0
|
||||
tweaked = true
|
||||
end
|
||||
|
||||
# there is at least one track with volume specified.
|
||||
if !track["mute"] && track["vol"] != 0
|
||||
all_quiet = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if all_quiet
|
||||
errors.add(:settings, 'are all muted')
|
||||
end
|
||||
if !tweaked
|
||||
errors.add(:settings, 'have nothing specified')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -114,12 +114,14 @@ module JamRuby
|
|||
vol = 1.0
|
||||
pan = 0
|
||||
match = false
|
||||
skipped = false
|
||||
# is this stem in the altered_tracks list?
|
||||
altered_tracks.each do |alteration|
|
||||
|
||||
if alteration["id"] == stem.id
|
||||
if alteration["mute"] || alteration["vol"] == 0
|
||||
log.debug("leaving out track because muted or 0 volume")
|
||||
log.debug("leaving out track because muted or 0 volume #{alteration.inspect}")
|
||||
skipped = true
|
||||
next
|
||||
else
|
||||
vol = alteration["vol"] || vol
|
||||
|
|
@ -131,7 +133,8 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
unless match
|
||||
# if we didn't deliberately skip this one, and if there was no 'match' (meaning user did not specify), then we leave this in unchanged
|
||||
if !skipped && !match
|
||||
@track_settings << {stem:stem, vol:vol, pan:pan}
|
||||
end
|
||||
end
|
||||
|
|
@ -146,7 +149,7 @@ module JamRuby
|
|||
# k = f(i) = (i)/(2*MAX_PAN) + 0.5
|
||||
# so f(MIN_PAN) = -0.5 + 0.5 = 0
|
||||
|
||||
k = ((i * (1.0))/ (2.0 * MAX_PAN )) + 0.5
|
||||
k = ((pan * (1.0))/ (2.0 * MAX_PAN )) + 0.5
|
||||
l, r = 0
|
||||
|
||||
if k == 0
|
||||
|
|
@ -165,6 +168,7 @@ module JamRuby
|
|||
puts @settings.inspect
|
||||
puts @track_count
|
||||
puts @track_settings
|
||||
puts @track_settings.count
|
||||
|
||||
Dir.mktmpdir do |tmp_dir|
|
||||
|
||||
|
|
@ -217,6 +221,8 @@ module JamRuby
|
|||
else
|
||||
pan_l, pan_r = slider_to_pan(track[:pan])
|
||||
|
||||
vol = track[:vol]
|
||||
|
||||
# short
|
||||
channel_l = pan_l * vol
|
||||
channel_r = pan_r * vol
|
||||
|
|
@ -227,7 +233,7 @@ module JamRuby
|
|||
|
||||
volumed_file = File.join(tmp_dir, jam_track_track.id + '-volumed.ogg')
|
||||
|
||||
cmd("sox \"#{file}\" \"#{volumed_file}\" remix 1v#{channel_l} 2v#{channel_r}")
|
||||
cmd("sox \"#{file}\" \"#{volumed_file}\" remix 1v#{channel_r} 2v#{channel_l}", 'vol_pan')
|
||||
|
||||
track[:volumed_file] = volumed_file
|
||||
end
|
||||
|
|
@ -239,21 +245,30 @@ module JamRuby
|
|||
|
||||
bump_step(@mixdown_package)
|
||||
|
||||
# sox -m will divide by number of inputs by default. But we purposefully leave out tracks that are mute/no volume (to save downloading/processing time in this job)
|
||||
# so we need to tell sox to divide by how many tracks there are as a constant, because this is how the client works today
|
||||
#sox -m -v 1/n file1 -v 1/n file2 out
|
||||
cmd = "sox -m"
|
||||
mix_divide = 1.0/@track_count
|
||||
@track_settings.each do |track|
|
||||
volumed_file = track[:volumed_file]
|
||||
cmd << " -v #{mix_divide} \"#{volumed_file}\""
|
||||
@mix_file = File.join(tmp_dir, "mix.ogg")
|
||||
|
||||
# if there is only one track to mix, we need to skip mixing (sox will barf if you try to mix one file), but still divide by number of tracks
|
||||
if @track_settings.count == 1
|
||||
mix_divide = 1.0/@track_count
|
||||
cmd = "sox -v #{mix_divide} \"#{@track_settings[0][:volumed_file]}\" \"#{@mix_file}\""
|
||||
cmd(cmd, 'volume_adjust')
|
||||
else
|
||||
# sox -m will divide by number of inputs by default. But we purposefully leave out tracks that are mute/no volume (to save downloading/processing time in this job)
|
||||
# so we need to tell sox to divide by how many tracks there are as a constant, because this is how the client works today
|
||||
#sox -m -v 1/n file1 -v 1/n file2 out
|
||||
cmd = "sox -m"
|
||||
mix_divide = 1.0/@track_count
|
||||
@track_settings.each do |track|
|
||||
volumed_file = track[:volumed_file]
|
||||
cmd << " -v #{mix_divide} \"#{volumed_file}\""
|
||||
end
|
||||
|
||||
|
||||
cmd << " \"#{@mix_file}\""
|
||||
cmd(cmd, 'mix_adjust')
|
||||
end
|
||||
|
||||
|
||||
@mix_file = File.join(tmp_dir, "mix.ogg")
|
||||
|
||||
cmd << " \"#{@mix_file}\""
|
||||
cmd(cmd)
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -335,7 +350,7 @@ module JamRuby
|
|||
|
||||
raise 'unknown file_type' if @mixdown_package.file_type != JamTrackMixdownPackage::FILE_TYPE_AAC
|
||||
|
||||
cmd("ffmpeg -i \"#{@speed_mix_file}\" -c:a libfdk_aac -b:a 128k \"#{output}\"")
|
||||
cmd("ffmpeg -i \"#{@speed_mix_file}\" -c:a libfdk_aac -b:a 128k \"#{output}\"", 'convert_aac')
|
||||
output
|
||||
end
|
||||
end
|
||||
|
|
@ -357,6 +372,25 @@ module JamRuby
|
|||
py_file = File.join(py_root, "jkcreate.py")
|
||||
version = @mixdown_package.version
|
||||
|
||||
right = @mixdown.jam_track.right_for_user(@mixdown.user)
|
||||
|
||||
if @mixdown_package.sample_rate == 48
|
||||
private_key = right.private_key_48
|
||||
else
|
||||
private_key = right.private_key_44
|
||||
end
|
||||
|
||||
unless private_key
|
||||
@error_reason = 'no_private_key'
|
||||
@error_detail = 'user needs to generate JamTrack for given sample rate'
|
||||
raise @error_reason
|
||||
end
|
||||
|
||||
private_key_file = File.join(tmp_dir, 'skey.pem')
|
||||
File.open(private_key_file, 'w') {|f| f.write(private_key) }
|
||||
|
||||
log.debug("PRIVATE KEY")
|
||||
log.debug(private_key)
|
||||
log.info "Executing python source in #{py_file}, outputting to #{tmp_dir} (#{output})"
|
||||
|
||||
cli = "python #{py_file} -D -k #{sku} -p #{Shellwords.escape(tmp_dir)}/pkey.pem -s #{Shellwords.escape(tmp_dir)}/skey.pem #{jam_file_opts} -o #{Shellwords.escape(output)} -t #{Shellwords.escape(title)} -V #{Shellwords.escape(version)}"
|
||||
|
|
@ -370,12 +404,12 @@ module JamRuby
|
|||
raise ArgumentError, "Error calling python script: #{err}" if err.present?
|
||||
raise ArgumentError, "Error calling python script: #{out}" if out && (out.index("No track files specified") || out.index("Cannot find file"))
|
||||
|
||||
private_key = File.read("#{tmp_dir}/skey.pem")
|
||||
private_key = File.read(private_key_file)
|
||||
end
|
||||
return output, private_key
|
||||
end
|
||||
|
||||
def cmd(cmd)
|
||||
def cmd(cmd, type)
|
||||
|
||||
log.debug("executing #{cmd}")
|
||||
|
||||
|
|
@ -386,6 +420,8 @@ module JamRuby
|
|||
if result_code == 0
|
||||
output
|
||||
else
|
||||
@error_reason = type + "_fail"
|
||||
@error_detail = "#{cmd}, #{output}"
|
||||
raise "command `#{cmd}` failed."
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
showDownloading: () =>
|
||||
@logger.debug("showing #{@state.name}")
|
||||
# while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually
|
||||
context.jamClient.JamTrackDownload(@jamTrack.id, context.JK.currentUserId,
|
||||
context.jamClient.JamTrackDownload(@jamTrack.id, null, context.JK.currentUserId,
|
||||
this.makeDownloadProgressCallback(),
|
||||
this.makeDownloadSuccessCallback(),
|
||||
this.makeDownloadFailureCallback())
|
||||
|
|
|
|||
|
|
@ -505,6 +505,9 @@
|
|||
return 0;
|
||||
}
|
||||
|
||||
function GetJamTrackSettings() {
|
||||
return {tracks:[]}
|
||||
}
|
||||
function SessionGetJamTracksPlayDurationMs() {
|
||||
return 60000;
|
||||
}
|
||||
|
|
@ -1214,6 +1217,7 @@
|
|||
this.TrackGetChatUsesMusic = TrackGetChatUsesMusic;
|
||||
this.TrackSetChatUsesMusic = TrackSetChatUsesMusic;
|
||||
|
||||
this.GetJamTrackSettings = GetJamTrackSettings;
|
||||
this.JamTrackStopPlay = JamTrackStopPlay;
|
||||
this.JamTrackPlay = JamTrackPlay;
|
||||
this.JamTrackIsPlayable = JamTrackIsPlayable;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//= require react-input-autosize
|
||||
//= require react-select
|
||||
//= require react_rails_img
|
||||
// //= require react_rails_img
|
||||
//= require_directory ./react-components/helpers
|
||||
//= require_directory ./react-components/actions
|
||||
//= require ./react-components/stores/AppStore
|
||||
|
|
|
|||
|
|
@ -38,9 +38,11 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
@state.controls.onPlayStopEvent()
|
||||
else if changes.playbackState == 'play_pause'
|
||||
@state.controls.onPlayPauseEvent();
|
||||
else if changes.positionUpdateChanged
|
||||
if changes.positionUpdateChanged
|
||||
if @state.controls?
|
||||
@state.controls.executeMonitor(changes.positionMs, changes.durationMs, changes.isPlaying)
|
||||
if changes.currentTimeChanged
|
||||
@setState({time: changes.time})
|
||||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
|
|
@ -69,8 +71,8 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
|
||||
monitorControls: (controls, mediaSummary) ->
|
||||
|
||||
if mediaSummary.mediaOpen
|
||||
if mediaSummary.jamTrackOpen
|
||||
if mediaSummary.mediaOpen || mediaSummary.jamTrack?
|
||||
if mediaSummary.jamTrack?
|
||||
controls.startMonitor(PLAYBACK_MONITOR_MODE.JAMTRACK)
|
||||
else if mediaSummary.backingTrackOpen
|
||||
controls.startMonitor(PLAYBACK_MONITOR_MODE.MEDIA_FILE)
|
||||
|
|
@ -163,7 +165,7 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="recording-time start-time">0:00</div>
|
||||
<div className="recording-time start-time">{this.state.time}</div>
|
||||
<div className="recording-playback">
|
||||
<div className="recording-slider"><img src="/assets/content/slider_playcontrols.png" height="16" width="5" /></div>
|
||||
</div>
|
||||
|
|
@ -179,7 +181,7 @@ mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
|||
|
||||
|
||||
getInitialState: () ->
|
||||
{controls: null, mediaSummary: {}, initializedMetronomeControls: false}
|
||||
{controls: null, mediaSummary: {}, initializedMetronomeControls: false, time: '0:00'}
|
||||
|
||||
tryPrepareMetronome: (metro) ->
|
||||
if @state.mediaSummary.metronomeOpen && !@state.initializedMetronomeControls
|
||||
|
|
|
|||
|
|
@ -17,17 +17,16 @@ if window.opener?
|
|||
|
||||
if accessOpener
|
||||
SessionActions = window.opener.SessionActions
|
||||
MediaPlaybackStore = window.opener.MediaPlaybackStore
|
||||
MixerActions = window.opener.MixerActions
|
||||
JamTrackActions = window.opener.JamTrackActions
|
||||
JamTrackMixdownActions = window.opener.JamTrackMixdownActions
|
||||
#JamTrackMixdownStore = window.opener.JamTrackMixdownStore
|
||||
JamTrackMixdown = window.opener.JamTrackMixdown
|
||||
JamTrackStore = window.opener.JamTrackStore
|
||||
MixerStore = window.opener.MixerStore
|
||||
SessionStore = window.opener.SessionStore
|
||||
|
||||
mixins.push(Reflux.listenTo(MixerStore, 'onMixersChanged'))
|
||||
mixins.push(Reflux.listenTo(MediaPlaybackStore, 'onMediaStateChanged'))
|
||||
#mixins.push(Reflux.listenTo(JamTrackMixdownStore, 'onJamTrackMixdownChanged'))
|
||||
mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
||||
|
||||
@PopupMediaControls = React.createClass({
|
||||
|
|
@ -51,7 +50,7 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
recordingName: mixers.recordingName()
|
||||
jamTrackName: mixers.jamTrackName()
|
||||
|
||||
@setState(media: state)
|
||||
@setState(media: state, downloadingJamTrack: session.downloadingJamTrack)
|
||||
|
||||
onMediaStateChanged: (changes) ->
|
||||
if changes.currentTimeChanged && @root?
|
||||
|
|
@ -70,7 +69,15 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
SessionActions.showNativeMetronomeGui()
|
||||
|
||||
getInitialState: () ->
|
||||
{media: @props.media, time: '0:00', mixdown: @props.mixdown, jamTrackState: @props.jamTrackState, creatingMixdown: false, createMixdownErrors: null}
|
||||
{
|
||||
media: @props.media,
|
||||
mixdown: @props.mixdown,
|
||||
jamTrackState: @props.jamTrackState,
|
||||
creatingMixdown: false,
|
||||
createMixdownErrors: null,
|
||||
editingMixdownId: null,
|
||||
downloadingJamTrack: @props.downloadingJamTrack
|
||||
}
|
||||
|
||||
close: () ->
|
||||
window.close()
|
||||
|
|
@ -87,7 +94,7 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
mediaType = "Recording"
|
||||
mediaName = @state.media.recordedTracks[0].recordingName
|
||||
closeLinkText = 'close recording'
|
||||
header = `<h3>{mediaType}: {mediaName} ({this.state.time})</h3>`
|
||||
header = `<h3>{mediaType}: {mediaName}</h3>`
|
||||
else if @state.jamTrackState.jamTrack?
|
||||
jamTrack = @state.jamTrackState.jamTrack
|
||||
mediaType = "JamTrack"
|
||||
|
|
@ -95,20 +102,41 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
closeLinkText = 'CLOSE JAMTRACK'
|
||||
|
||||
|
||||
selectedMixdown = null
|
||||
if jamTrack.last_mixdown_id
|
||||
selectedMixdowns = jamTrack.mixdowns.filter((mixdown) -> jamTrack.last_mixdown_id == mixdown.id)
|
||||
selectedMixdown = selectedMixdowns[0] if selectedMixdowns.length > 0
|
||||
selectedMixdown = jamTrack.activeMixdown
|
||||
|
||||
|
||||
if selectedMixdown?
|
||||
jamTrackTypeHeader = 'Custom Mix'
|
||||
customMixName = `<h5>{selectedMixdown.name}</h5>`
|
||||
|
||||
disabled = true
|
||||
if selectedMixdown.client_state?
|
||||
switch selectedMixdown.client_state
|
||||
when 'cant_open'
|
||||
customMixName = `<h5>L: {selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'keying_timeout'
|
||||
customMixName = `<h5>K: {selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'download_fail'
|
||||
customMixName = `<h5>D: {selectedMixdown.name}<img src="/assets/content/icon-mix-fail@2X.png" /></h5>`
|
||||
when 'keying'
|
||||
customMixName = `<h5>K: Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
when 'downloading'
|
||||
customMixName = `<h5>D: Loading selected mix... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
when 'ready'
|
||||
customMixName = `<h5>{selectedMixdown.name}</h5>`
|
||||
disabled = false
|
||||
else
|
||||
customMixName = `<h5>Creating mixdown... <img src="/assets/shared/spinner.gif" /></h5>`
|
||||
|
||||
else
|
||||
jamTrackTypeHeader = 'Full JamTrack'
|
||||
logger.debug("STATE!", @state.downloadingJamTrack)
|
||||
if SessionStore.downloadingJamTrack
|
||||
downloader = `<img src="/assets/shared/spinner.gif" />`
|
||||
|
||||
jamTrackTypeHeader = `<span>Full JamTrack {downloader}</span>`
|
||||
|
||||
header = `
|
||||
<div className="header">
|
||||
<h3>{mediaType}: {mediaName} ({this.state.time})</h3>
|
||||
<h3>{mediaType}: {mediaName}</h3>
|
||||
<h4>{jamTrackTypeHeader}</h4>
|
||||
{customMixName}
|
||||
</div>`
|
||||
|
|
@ -116,19 +144,37 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
myMixes = null
|
||||
if @state.showMyMixes
|
||||
myMixdowns = []
|
||||
|
||||
boundPlayClick = this.jamTrackPlay.bind(this, jamTrack);
|
||||
|
||||
active = jamTrack.last_mixdown_id == null
|
||||
|
||||
myMixdowns.push `
|
||||
<div key="full-track" className={classNames({'full-track': true, 'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
Full JamTrack
|
||||
</div>
|
||||
<div className="mixdown-actions">
|
||||
<img src="/assets/content/icon_open@2X.png" className="mixdown-play" onClick={boundPlayClick}/>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
for mixdown in jamTrack.mixdowns
|
||||
boundPlayClick = this.mixdownPlay.bind(this, mixdown);
|
||||
boundEditClick = this.mixdownEdit.bind(this, mixdown);
|
||||
boundSaveClick = this.mixdownSave.bind(this, mixdown);
|
||||
boundDeleteClick = this.mixdownDelete.bind(this, mixdown);
|
||||
boundErrorClick = this.mixdownError.bind(this, mixdown);
|
||||
boundEditKeydown = this.onEditKeydown.bind(this, mixdown);
|
||||
|
||||
mixdown_package = mixdown.myPackage
|
||||
|
||||
active = mixdown.id == jamTrack.last_mixdown_id
|
||||
|
||||
editing = mixdown.id == @state.editingMixdownId
|
||||
|
||||
# if there is a package, check it's state; otherwise let the user enqueue it
|
||||
if mixdown_package
|
||||
logger.debug("MY PACKAGE STATE", mixdown_package.signing_state)
|
||||
switch mixdown_package.signing_state
|
||||
when 'QUIET_TIMEOUT'
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
|
|
@ -149,22 +195,28 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
else
|
||||
action = `<img src="/assets/content/icon-mix-fail@2X.png" className="mixdown-play" onClick={boundErrorClick}/>`
|
||||
|
||||
if editing
|
||||
mixdownName = `<input className="edit-name" type="text" defaultValue={mixdown.name} onKeyDown={boundEditKeydown} />`
|
||||
editIcon = `<img src="/assets/content/icon-save@2X.png" className="mixdown-edit" onClick={boundSaveClick}/>`
|
||||
else
|
||||
mixdownName = mixdown.name
|
||||
editIcon = `<img src="/assets/content/icon-edit@2X.png" className="mixdown-edit" onClick={boundEditClick}/>`
|
||||
|
||||
myMixdowns.push `
|
||||
<div key={mixdown.id} className={classNames({'mixdown-display': true, 'active' : active})}>
|
||||
<div className="mixdown-name">
|
||||
{mixdown.name}
|
||||
{mixdownName}
|
||||
</div>
|
||||
<div className="mixdown-actions">
|
||||
{action}
|
||||
|
||||
<Img src="/assets/content/icon-edit@2X.png" className="mixdown-edit" onClick={boundEditClick}/>
|
||||
{editIcon}
|
||||
|
||||
<Img src ="/assets/content/icon-delete@2X.png" className="mixdown-delete" onClick={boundDeleteClick} />
|
||||
<img src ="/assets/content/icon-delete@2X.png" className="mixdown-delete" onClick={boundDeleteClick} />
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
myMixes = `<div key="my-mixes" className="my-mixes">{myMixdowns}</div>`
|
||||
myMixes = `<div key="my-mixes" className="my-mixes">{myMixdowns}</div>`
|
||||
|
||||
mixControls = null
|
||||
if @state.showCustomMixes
|
||||
|
|
@ -172,7 +224,7 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
nameClassData = {field: true}
|
||||
if @state.createMixdownErrors?
|
||||
|
||||
errorHtml = context.JK.reactErrors(@state.createMixdownErrors, {name: 'Mix Name', settings: 'Settings'})
|
||||
errorHtml = context.JK.reactErrors(@state.createMixdownErrors, {name: 'Mix Name', settings: 'Settings', jam_track: 'JamTrack'})
|
||||
|
||||
createMixClasses = classNames({'button-orange' : true, 'create-mix-btn' : true, 'disabled' : @state.creatingMixdown})
|
||||
mixControls = `
|
||||
|
|
@ -278,7 +330,7 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
mediaType = "Audio File"
|
||||
mediaName = context.JK.getNameOfFile(@state.media.backingTracks[0].shortFilename)
|
||||
closeLinkText = 'CLOSE AUDIO FILE'
|
||||
header = `<h3>{mediaType}: {mediaName} ({this.state.time})</h3>`
|
||||
header = `<h3>{mediaType}: {mediaName}</h3>`
|
||||
extraControls =
|
||||
`<div>
|
||||
<div className="field">
|
||||
|
|
@ -313,17 +365,57 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
|
||||
toggleCustomMixes: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
@setState({showCustomMixes: !@state.showCustomMixes})
|
||||
|
||||
mixdownPlay: (mixdown, e) ->
|
||||
@setState({editingMixdownId: null})
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
if @disableLoading
|
||||
$target = $(e.target)
|
||||
context.JK.prodBubble($target, 'no-change-while-loading', {}, {positions:['left', 'top']})
|
||||
return
|
||||
|
||||
# make this package the active one
|
||||
JamTrackMixdownActions.openMixdown(mixdown)
|
||||
|
||||
jamTrackPlay: (jamtrack, e) ->
|
||||
e.preventDefault()
|
||||
# user wants to select the full track
|
||||
|
||||
if @disableLoading
|
||||
$target = $(e.target)
|
||||
context.JK.prodBubble($target, 'no-change-while-loading', {}, {positions:['left', 'top']})
|
||||
return
|
||||
|
||||
JamTrackActions.activateNoMixdown(jamtrack)
|
||||
|
||||
onEditKeydown: (mixdown, e) ->
|
||||
logger.debug("on edit keydown", e)
|
||||
if e.keyCode == 13 # enter
|
||||
@mixdownSave(mixdown, e)
|
||||
else if e.keyCode == 27 # esc
|
||||
@setState({editingMixdownId: null})
|
||||
|
||||
mixdownEdit: (mixdown) ->
|
||||
@setState({editingMixdownId: mixdown.id})
|
||||
|
||||
mixdownSave: (mixdown, e) ->
|
||||
e.preventDefault()
|
||||
$input = $(this.getDOMNode()).find('input.edit-name')
|
||||
newValue = $input.val()
|
||||
logger.debug("editing mixdown name to be: " + newValue)
|
||||
JamTrackMixdownActions.editMixdown({id: mixdown.id, name: newValue})
|
||||
@setState({editingMixdownId: null})
|
||||
|
||||
mixdownDelete: (mixdown) ->
|
||||
JamTrackAction.deleteMixdown(mixdown)
|
||||
if confirm("Delete this custom mix?")
|
||||
|
||||
@setState({editingMixdownId:null})
|
||||
JamTrackMixdownActions.deleteMixdown(mixdown)
|
||||
|
||||
|
||||
mixdownError: (mixdown) ->
|
||||
alert("error")
|
||||
|
|
@ -339,6 +431,10 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
speed = $root.find('select[name="mix-speed"]').val()
|
||||
pitch = $root.find('select[name="mix-pitch"]').val()
|
||||
|
||||
if @state.jamTrackState.jamTrack?.activeMixdown?
|
||||
@setState({createMixdownErrors: {errors: {'Full JamTrack': ['must be selected']}}})
|
||||
return
|
||||
|
||||
if name == null || name == ''
|
||||
@setState({createMixdownErrors: {errors: {'Mix Name': ["can't be blank"]}}})
|
||||
return
|
||||
|
|
@ -353,7 +449,6 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
else
|
||||
pitch = parseInt(pitch)
|
||||
|
||||
|
||||
mixdown = {jamTrackID: @state.jamTrackState.jamTrack.id, name: name, settings: {speed:speed, pitch: pitch}}
|
||||
|
||||
package_settings = {file_type: 'ogg', encrypt_type: 'jkz'}
|
||||
|
|
@ -419,4 +514,25 @@ mixins.push(Reflux.listenTo(JamTrackStore, 'onJamTrackChanged'))
|
|||
#offset += 25
|
||||
|
||||
window.resizeTo(width, height + offset)
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
|
||||
@disableLoading = false
|
||||
|
||||
return unless nextState?
|
||||
|
||||
selectedMixdown = nextState?.jamTrackState?.jamTrack?.activeMixdown
|
||||
|
||||
mixdownDownloading = false
|
||||
if selectedMixdown?
|
||||
switch selectedMixdown.client_state
|
||||
when 'keying'
|
||||
mixdownDownloading = true
|
||||
when 'downloading'
|
||||
mixdownDownloading = true
|
||||
|
||||
|
||||
@disableLoading = SessionStore.downloadingJamTrack || mixdownDownloading
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -15,9 +15,18 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
Reflux.listenTo(@JamTrackStore, "onJamTrackStateChanged")]
|
||||
|
||||
onJamTrackStateChanged: (jamTrackState) ->
|
||||
if jamTrackState.opened
|
||||
if jamTrackState.fullTrackActivated || jamTrackState.opened && jamTrackState.jamTrack.activeMixdown == null
|
||||
@loadJamTrack(jamTrackState.jamTrack)
|
||||
else if jamTrackState.closed
|
||||
logger.debug("SessionMediaTracks: jamtrack has been closed")
|
||||
|
||||
if @state.downloadJamTrack?
|
||||
logger.debug("closing DownloadJamTrack widget")
|
||||
@state.downloadJamTrack.root.remove()
|
||||
@state.downloadJamTrack.destroy()
|
||||
SessionActions.downloadingJamTrack(false)
|
||||
@setState({downloadJamTrack: null})
|
||||
|
||||
SessionActions.closeMedia(true)
|
||||
|
||||
#inputsChangedProcessed: (state) ->
|
||||
|
|
@ -264,8 +273,8 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
# All the JamTracks
|
||||
mediaTracks.push(`<SessionJamTrackCategory key="JamTrackCategory" jamTrackName={this.state.jamTrackName} mixers={this.state.mediaCategoryMixer} mode={MIX_MODES.PERSONAL} />`)
|
||||
|
||||
|
||||
if @state.metronome?
|
||||
# show metronome only if it's a full jamtrack
|
||||
if @state.metronome? && @state.jamTrackMixdown.id == null
|
||||
@state.metronome.mode = MIX_MODES.PERSONAL
|
||||
mediaTracks.push(`<SessionMetronome key="JamTrackMetronome" {...this.state.metronome} location="jam-track" />`)
|
||||
|
||||
|
|
@ -338,7 +347,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds
|
|||
unless @childWindow?
|
||||
logger.debug("opening media control window")
|
||||
@childWindow = window.open("/popups/media-controls", 'Media Controls', 'scrollbars=yes,toolbar=no,status=no,height=155,width=350')
|
||||
@childWindow.PopupProps = {media: @state, jamTrackState: context.JamTrackStore.getState()}
|
||||
@childWindow.PopupProps = {media: @state, jamTrackState: context.JamTrackStore.getState(), downloadingJamTrack: context.SessionStore.downloadingJamTrack }
|
||||
else
|
||||
if @childWindow?
|
||||
@childWindow.DontAutoCloseMedia = true
|
||||
|
|
|
|||
|
|
@ -113,9 +113,10 @@ ptrCount = 0
|
|||
context.JK.checkbox($checkbox)
|
||||
$checkbox.on('ifChanged', this.handleMuteCheckbox);
|
||||
|
||||
|
||||
# using iCheck causes a 'ifChanged' event, so we need to swallow this up
|
||||
@iCheckMaint = true
|
||||
if muteMixer.mute
|
||||
if muteMixer?.mute
|
||||
$checkbox.iCheck('check').attr('checked', true)
|
||||
else
|
||||
$checkbox.iCheck('uncheck').attr('checked', false)
|
||||
|
|
@ -139,7 +140,7 @@ ptrCount = 0
|
|||
|
||||
# using iCheck causes a 'ifChanged' event, so we need to swallow this up
|
||||
@iCheckMaint = true
|
||||
if muteMixer.mute
|
||||
if muteMixer?.mute
|
||||
$checkbox.iCheck('check').attr('checked', true)
|
||||
else
|
||||
$checkbox.iCheck('uncheck').attr('checked', false)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ context = window
|
|||
@JamTrackActions = Reflux.createActions({
|
||||
open: {}
|
||||
close: {}
|
||||
activateNoMixdown: {}
|
||||
requestSearch: {}
|
||||
requestFilter: {}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -19,4 +19,5 @@ context = window
|
|||
broadcastFailure: {}
|
||||
broadcastSuccess: {}
|
||||
broadcastStopped: {}
|
||||
mixdownActive: {}
|
||||
})
|
||||
|
|
@ -299,6 +299,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
jamTrackMixers = @jamTrackMixers.slice();
|
||||
jamTracks = []
|
||||
jamTrackName = null;
|
||||
jamTrackMixdown = {id: null}
|
||||
|
||||
if @session.isPlayingRecording()
|
||||
# only return managed mixers for recorded backing tracks
|
||||
|
|
@ -308,6 +309,7 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
# only return un-managed (ad-hoc) mixers for normal backing tracks
|
||||
jamTracks = @session.jamTracks()
|
||||
jamTrackName = @session.jamTrackName()
|
||||
jamTrackMixdown = @session.jamTrackMixdown()
|
||||
|
||||
# pluck the 1st mixer, and assume that all other mixers in this group are of the same type (between JamTrack vs Peer)
|
||||
# if it's a locally opened track (JamTrackGroup), then we can say this person is the opener
|
||||
|
|
@ -315,55 +317,90 @@ MIX_MODES = context.JK.MIX_MODES;
|
|||
|
||||
if jamTracks
|
||||
noCorrespondingTracks = false
|
||||
for jamTrack in jamTracks
|
||||
mixer = null
|
||||
preMasteredClass = ""
|
||||
# find the track or tracks that correspond to the mixer
|
||||
correspondingTracks = []
|
||||
|
||||
for matchMixer in @jamTrackMixers
|
||||
if matchMixer.id == jamTrack.id
|
||||
correspondingTracks.push(jamTrack)
|
||||
mixer = matchMixer
|
||||
|
||||
if correspondingTracks.length == 0
|
||||
# Are we opening a mixdown, or a full track?
|
||||
if jamTrackMixdown.id?
|
||||
logger.debug("MixerHelper: mixdown is active. id: #{jamTrackMixdown.id}")
|
||||
if jamTrackMixers.length == 0
|
||||
noCorrespondingTracks = true
|
||||
logger.error("could not correlate jam tracks", jamTrackMixers, jamTracks)
|
||||
logger.error("could not correlate mixdown tracks", jamTrackMixers, jamTrackMixdown)
|
||||
@app.notify({
|
||||
title: "Unable to Open JamTrack",
|
||||
title: "Unable to Open Custom Mix",
|
||||
text: "Could not correlate server and client tracks",
|
||||
icon_url: "/assets/content/icon_alert_big.png"})
|
||||
return _jamTracks
|
||||
|
||||
#jamTracks = $.grep(jamTracks, (value) =>
|
||||
# $.inArray(value, correspondingTracks) < 0
|
||||
#)
|
||||
|
||||
# prune found mixers
|
||||
jamTrackMixers.splice(mixer);
|
||||
|
||||
oneOfTheTracks = correspondingTracks[0];
|
||||
instrumentIcon = context.JK.getInstrumentIcon24(oneOfTheTracks.instrument.id);
|
||||
|
||||
part = oneOfTheTracks.part
|
||||
|
||||
instrumentName = oneOfTheTracks.instrument.description
|
||||
|
||||
if part?
|
||||
trackName = "#{instrumentName}: #{part}"
|
||||
else if jamTrackMixers.length > 1
|
||||
logger.warn("ignoring wrong amount of mixers for JamTrack in mixdown mode")
|
||||
return _jamTracks
|
||||
else
|
||||
trackName = instrumentName
|
||||
|
||||
data =
|
||||
name: jamTrackName
|
||||
trackName: trackName
|
||||
part: part
|
||||
isOpener: isOpener
|
||||
instrumentIcon: instrumentIcon
|
||||
track: oneOfTheTracks
|
||||
mixers: @mediaMixers(mixer, isOpener)
|
||||
instrumentIcon = context.JK.getInstrumentIcon24('other')
|
||||
part = null
|
||||
instrumentName = 'Custom Mix'
|
||||
trackName = 'Custom Mix'
|
||||
|
||||
_jamTracks.push(data)
|
||||
data =
|
||||
name: jamTrackName
|
||||
trackName: trackName
|
||||
part: part
|
||||
isOpener: isOpener
|
||||
instrumentIcon: instrumentIcon
|
||||
track: jamTrackMixdown
|
||||
mixers: @mediaMixers(jamTrackMixers[0], isOpener)
|
||||
|
||||
_jamTracks.push(data)
|
||||
else
|
||||
logger.debug("MixerHelper: full jamtrack is active")
|
||||
|
||||
for jamTrack in jamTracks
|
||||
mixer = null
|
||||
preMasteredClass = ""
|
||||
# find the track or tracks that correspond to the mixer
|
||||
correspondingTracks = []
|
||||
|
||||
for matchMixer in @jamTrackMixers
|
||||
if matchMixer.id == jamTrack.id
|
||||
correspondingTracks.push(jamTrack)
|
||||
mixer = matchMixer
|
||||
|
||||
if correspondingTracks.length == 0
|
||||
noCorrespondingTracks = true
|
||||
logger.error("could not correlate jam tracks", jamTrackMixers, jamTracks)
|
||||
@app.notify({
|
||||
title: "Unable to Open JamTrack",
|
||||
text: "Could not correlate server and client tracks",
|
||||
icon_url: "/assets/content/icon_alert_big.png"})
|
||||
return _jamTracks
|
||||
|
||||
#jamTracks = $.grep(jamTracks, (value) =>
|
||||
# $.inArray(value, correspondingTracks) < 0
|
||||
#)
|
||||
|
||||
# prune found mixers
|
||||
jamTrackMixers.splice(mixer);
|
||||
|
||||
oneOfTheTracks = correspondingTracks[0];
|
||||
instrumentIcon = context.JK.getInstrumentIcon24(oneOfTheTracks.instrument.id);
|
||||
|
||||
part = oneOfTheTracks.part
|
||||
|
||||
instrumentName = oneOfTheTracks.instrument.description
|
||||
|
||||
if part?
|
||||
trackName = "#{instrumentName}: #{part}"
|
||||
else
|
||||
trackName = instrumentName
|
||||
|
||||
data =
|
||||
name: jamTrackName
|
||||
trackName: trackName
|
||||
part: part
|
||||
isOpener: isOpener
|
||||
instrumentIcon: instrumentIcon
|
||||
track: oneOfTheTracks
|
||||
mixers: @mediaMixers(mixer, isOpener)
|
||||
|
||||
_jamTracks.push(data)
|
||||
|
||||
_jamTracks
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ context = window
|
|||
else
|
||||
null
|
||||
|
||||
jamTrackMixdown: () ->
|
||||
{ id: @session?.jam_track?.mixdown.id }
|
||||
|
||||
jamTrackName: () ->
|
||||
@session?.jam_track?.name
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ logger = context.JK.logger
|
|||
mediaCategoryMixer: mediaCategoryMixer
|
||||
recordingName: mixers.recordingName()
|
||||
jamTrackName: mixers.jamTrackName()
|
||||
jamTrackMixdown: session.jamTrackMixdown()
|
||||
|
||||
@inputsChangedProcessed(state) if @inputsChangedProcessed?
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,12 @@ JamTrackActions = @JamTrackActions
|
|||
|
||||
return unless @jamTrack?
|
||||
|
||||
sampleRate = context.jamClient.GetSampleRate()
|
||||
sampleRate = if sampleRate == 48 then 48 else 44
|
||||
|
||||
for mixdown in @jamTrack.mixdowns
|
||||
|
||||
myPackage = null
|
||||
for mixdown_package in mixdown.packages
|
||||
if mixdown_package.file_type == 'ogg' && mixdown_package.encrypt_type == 'jkz' && mixdown_package.sample_rate == sampleRate
|
||||
if mixdown_package.file_type == 'ogg' && mixdown_package.encrypt_type == 'jkz' && mixdown_package.sample_rate == @sampleRate
|
||||
myPackage = mixdown_package
|
||||
break
|
||||
|
||||
|
|
@ -95,22 +93,162 @@ JamTrackActions = @JamTrackActions
|
|||
@changed()
|
||||
break
|
||||
|
||||
# this drives the state engine required to get a Mixdown from 'available on the server' to
|
||||
manageMixdownSynchronization: () ->
|
||||
|
||||
@jamTrack.activeMixdown = null if @jamTrack
|
||||
|
||||
# let's see if we have a mixdown active?
|
||||
|
||||
if !@jamTrack?.last_mixdown_id?
|
||||
logger.debug("JamTrackStore: no mixdown active")
|
||||
@clearMixdownTimers()
|
||||
return
|
||||
|
||||
for mixdown in @jamTrack.mixdowns
|
||||
if mixdown.id == @jamTrack.last_mixdown_id
|
||||
@jamTrack.activeMixdown = mixdown
|
||||
logger.debug("JamTrackStore: mixdown active:", mixdown)
|
||||
break
|
||||
|
||||
if @jamTrack.activeMixdown?
|
||||
|
||||
# if we don't have this on the server yet, don't engage the rest of this logic...
|
||||
return if @jamTrack.activeMixdown?.myPackage?.signing_state != 'SIGNED'
|
||||
|
||||
fqId = "#{@jamTrack.id}_#{@jamTrack.activeMixdown.id}-#{@sampleRate}"
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId)
|
||||
|
||||
logger.debug("JamTrackStore: JamTrackGetTrackDetail(#{fqId}).key_state: " + @trackDetail.key_state, @trackDetail)
|
||||
|
||||
# first check if the version is not the same; if so, invalidate.
|
||||
|
||||
if @trackDetail.version? && @jamTrack.activeMixdown.myPackage?
|
||||
if @jamTrack.activeMixdown.myPackage.version != @trackDetail.version
|
||||
logger.info("JamTrackStore: JamTrack Mixdown on disk is different version (stored: #{@trackDetail.version}, server: #{@jamTrack.activeMixdown.myPackage.version}. Invalidating")
|
||||
context.jamClient.InvalidateJamTrack(fqId)
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId)
|
||||
|
||||
if @trackDetail.version?
|
||||
logger.error("after invalidating package, the version is still wrong!")
|
||||
throw "after invalidating package, the version is still wrong!"
|
||||
|
||||
if @jamTrack.activeMixdown.client_state == 'cant_open'
|
||||
logger.debug(" skipping state check because of earlier 'cant_open'. user should hit retry. ")
|
||||
return
|
||||
|
||||
if @jamTrack.activeMixdown.client_state == 'download_fail'
|
||||
logger.debug("skipping state check because of earlier 'download_fail'. user should hit retry. ")
|
||||
return
|
||||
|
||||
if @jamTrack.activeMixdown.client_state == 'downloading'
|
||||
logger.debug("skipping state check because we are downloading")
|
||||
|
||||
switch @trackDetail.key_state
|
||||
when 'pending'
|
||||
@attemptKeying()
|
||||
when 'not authorized'
|
||||
# TODO: if not authorized, do we need to re-initiate a keying attempt?
|
||||
@attemptKeying()
|
||||
when 'ready'
|
||||
if @jamTrack.activeMixdown.client_state != 'ready'
|
||||
|
||||
@clearMixdownTimers()
|
||||
@jamTrack.activeMixdown.client_state = 'ready'
|
||||
|
||||
# now load it:
|
||||
# JamTrackPlay means 'load'
|
||||
logger.debug("JamTrackStore: loading mixdown")
|
||||
context.jamClient.JamTrackStopPlay();
|
||||
result = context.jamClient.JamTrackPlay(fqId);
|
||||
if !result
|
||||
@jamTrack.activeMixdown.client_state = 'cant_open'
|
||||
@app.notify(
|
||||
{
|
||||
title: "Mixdown Can Not Open",
|
||||
text: "Unable to open your JamTrack Mixdown. Please contact support@jamkazam.com"
|
||||
}
|
||||
, null, true)
|
||||
|
||||
when 'unknown'
|
||||
if @jamTrack.activeMixdown.client_state != 'downloading'
|
||||
@jamTrack.activeMixdown.client_state = 'downloading'
|
||||
logger.debug("JamTrackStore: initiating download of mixdown")
|
||||
context.jamClient.JamTrackDownload(@jamTrack.id, @jamTrack.activeMixdown.id, context.JK.currentUserId,
|
||||
this.makeDownloadProgressCallback(),
|
||||
this.makeDownloadSuccessCallback(),
|
||||
this.makeDownloadFailureCallback())
|
||||
else
|
||||
logger.debug("JamTrackStore: already downloading")
|
||||
|
||||
attemptKeying: () ->
|
||||
if @keyCheckTimeout?
|
||||
logger.debug("JamTrackStore: attemptKeying: skipping because already keying")
|
||||
return
|
||||
else if @jamTrack.activeMixdown.client_state == 'keying_timeout'
|
||||
# if we have timed out keying, we shouldn't automatically retry
|
||||
logger.debug("JamTrackStore: attempKeying: skipping because we have timed out before and user hasn't requested RETRY")
|
||||
return
|
||||
else
|
||||
@keyCheckTimeout = setTimeout(@onKeyCheckTimeout, 10000)
|
||||
@keyCheckoutInterval = setInterval(@checkOnKeying, 1000)
|
||||
@jamTrack.activeMixdown.client_state = 'keying'
|
||||
logger.debug("JamTrackStore: initiating keying requested")
|
||||
context.jamClient.JamTrackKeysRequest()
|
||||
|
||||
onKeyCheckTimeout: () ->
|
||||
@keyCheckTimeout = null
|
||||
clearInterval(@keyCheckoutInterval)
|
||||
@keyCheckoutInterval = null
|
||||
|
||||
if @jamTrack?.activeMixdown?
|
||||
@jamTrack.activeMixdown.client_state = 'keying_timeout'
|
||||
@changed()
|
||||
|
||||
checkOnKeying: () ->
|
||||
@manageMixdownSynchronization()
|
||||
|
||||
# if we exit keying state, we can clear our timers and poke state
|
||||
if @jamTrack.activeMixdown.client_state != 'keying'
|
||||
@clearMixdownTimers()
|
||||
@changed()
|
||||
|
||||
|
||||
# clear out any timer/watcher stuff
|
||||
clearMixdownTimers: () ->
|
||||
logger.debug("JamTrackStore: clearing mixdown timers", @keyCheckTimeout, @keyCheckoutInterval)
|
||||
clearTimeout(@keyCheckTimeout) if @keyCheckTimeout?
|
||||
clearInterval(@keyCheckoutInterval) if @keyCheckoutInterval?
|
||||
@keyCheckTimeout = null
|
||||
@keyCheckoutInterval = null
|
||||
|
||||
changed: () ->
|
||||
|
||||
@pickMyPackage()
|
||||
@manageWatchedMixdowns()
|
||||
@manageMixdownSynchronization()
|
||||
|
||||
@state = {jamTrack: @jamTrack, opened: @previous == null && @jamTrack != null, closed: @previous != null && @jamTrack == null}
|
||||
@state = {
|
||||
jamTrack: @jamTrack,
|
||||
opened: @previous == null && @jamTrack != null,
|
||||
closed: @previous != null && @jamTrack == null,
|
||||
fullTrackActivated: @previousMixdown != null && @jamTrack?.activeMixdown == null}
|
||||
@previous = @jamTrack
|
||||
@previousMixdown = @jamTrack?.activeMixdown
|
||||
this.trigger(@state)
|
||||
|
||||
|
||||
onOpen: (jamTrack) ->
|
||||
if @jamTrack?
|
||||
@app.notify({text: 'Unable to open JamTrack because another one is already open.'})
|
||||
return
|
||||
|
||||
@jamTrack = jamTrack
|
||||
|
||||
# we can cache this because you can't switch gear while in a session (and possible change sample rate!)
|
||||
sampleRate = context.jamClient.GetSampleRate()
|
||||
@sampleRate = if sampleRate == 48 then 48 else 44
|
||||
|
||||
@changed()
|
||||
|
||||
onClose: () ->
|
||||
|
|
@ -138,7 +276,18 @@ JamTrackActions = @JamTrackActions
|
|||
requested
|
||||
|
||||
onCreateMixdown: (mixdown, package_settings, done, fail) ->
|
||||
|
||||
volumeSettings = context.jamClient.GetJamTrackSettings();
|
||||
|
||||
track_settings = []
|
||||
|
||||
for track in volumeSettings.tracks
|
||||
track_settings.push({id: track.id, pan: track.pan, vol: track.vol_l, mute: track.mute})
|
||||
|
||||
mixdown.settings.tracks = track_settings
|
||||
|
||||
logger.debug("creating mixdown", mixdown, package_settings)
|
||||
|
||||
rest.createMixdown(mixdown)
|
||||
.done((created) =>
|
||||
|
||||
|
|
@ -149,9 +298,7 @@ JamTrackActions = @JamTrackActions
|
|||
package_settings.id = created.id
|
||||
|
||||
# we have to determine sample rate here, in the store, because child windows don't have access to jamClient
|
||||
sampleRate = context.jamClient.GetSampleRate()
|
||||
sampleRate = if sampleRate == 48 then 48 else 44
|
||||
package_settings.sample_rate = sampleRate
|
||||
package_settings.sample_rate = @sampleRate
|
||||
|
||||
rest.enqueueMixdown(package_settings)
|
||||
.done((enqueued) =>
|
||||
|
|
@ -160,7 +307,7 @@ JamTrackActions = @JamTrackActions
|
|||
done(enqueued)
|
||||
)
|
||||
.fail((jqxhr) =>
|
||||
@app.layout.notify({title:'Unable to Package Mixdown', text: 'You can push the RETRY button.'})
|
||||
@app.layout.notify({title:'Unable to Create Custom Mix', text: 'You can push the RETRY button.'})
|
||||
fail(jqxhr)
|
||||
)
|
||||
)
|
||||
|
|
@ -171,9 +318,27 @@ JamTrackActions = @JamTrackActions
|
|||
onEditMixdown: (mixdown) ->
|
||||
logger.debug("editing mixdown", mixdown)
|
||||
|
||||
rest.editMixdown(mixdown)
|
||||
.done((updatedMixdown) =>
|
||||
logger.debug("edited mixdown")
|
||||
@updateMixdown(updatedMixdown)
|
||||
).fail((jqxhr) =>
|
||||
@app.layout.notify({title:'Unable to Edit Custom Mix', text: 'The server was unable to edit this mix.'})
|
||||
)
|
||||
|
||||
onDeleteMixdown: (mixdown) ->
|
||||
logger.debug("deleting mixdown", mixdown)
|
||||
|
||||
rest.deleteMixdown(mixdown)
|
||||
.done(() =>
|
||||
logger.debug("deleted mixdown")
|
||||
|
||||
@deleteMixdown(mixdown)
|
||||
)
|
||||
.fail((jqxhr) =>
|
||||
@app.layout.notify({title:'Unable to Deleted Custom Mix', text: 'The server was unable to delete this mix.'})
|
||||
)
|
||||
|
||||
onOpenMixdown: (mixdown) ->
|
||||
logger.debug("opening mixdown", mixdown)
|
||||
|
||||
|
|
@ -182,12 +347,35 @@ JamTrackActions = @JamTrackActions
|
|||
.done((edited) =>
|
||||
logger.debug("marked mixdown as active")
|
||||
@jamTrack = edited
|
||||
|
||||
# unload any currently loaded JamTrack
|
||||
context.jamClient.JamTrackStopPlay();
|
||||
|
||||
@changed()
|
||||
|
||||
SessionActions.mixdownActive(mixdown)
|
||||
)
|
||||
.fail((jqxhr) =>
|
||||
@app.layout.notify({title:'Unable to Edit Mixdown', text: 'Unable to mark this mixdown as active.'})
|
||||
)
|
||||
|
||||
onActivateNoMixdown: (jamTrack) ->
|
||||
logger.debug("activating no mixdown")
|
||||
|
||||
rest.markMixdownActive({id: @jamTrack.id, mixdown_id: null})
|
||||
.done((edited) =>
|
||||
logger.debug("marked JamTrack as active")
|
||||
|
||||
@jamTrack = edited
|
||||
@changed()
|
||||
|
||||
SessionActions.mixdownActive({id:null})
|
||||
)
|
||||
.fail((jqxhr) =>
|
||||
@app.layout.notify({title:'Unable to Edit Mixdown', text: 'Unable to mark this mixdown as active.'})
|
||||
)
|
||||
|
||||
|
||||
onCloseMixdown: (mixdown) ->
|
||||
logger.debug("closing mixdown", mixdown)
|
||||
|
||||
|
|
@ -208,6 +396,41 @@ JamTrackActions = @JamTrackActions
|
|||
else
|
||||
logger.warn("no jamtrack to add mixdown to in JamTrackStore", mixdown)
|
||||
|
||||
deleteMixdown: (mixdown) ->
|
||||
if @jamTrack?
|
||||
logger.debug("deleting mixdown from JamTrackStore", mixdown)
|
||||
index = null
|
||||
for matchMixdown, i in @jamTrack.mixdowns
|
||||
if mixdown.id == matchMixdown.id
|
||||
index = i
|
||||
if index?
|
||||
@jamTrack.mixdowns.splice(index, 1)
|
||||
|
||||
if @jamTrack.activeMixdown?.id == mixdown.id
|
||||
@onActivateNoMixdown(@jamTrack)
|
||||
|
||||
@changed()
|
||||
else
|
||||
logger.warn("unable to find mixdown to delete in JamTrackStore", mixdown)
|
||||
else
|
||||
logger.warn("no jamtrack to delete mixdown for in JamTrackStore", mixdown)
|
||||
|
||||
updateMixdown: (mixdown) ->
|
||||
if @jamTrack?
|
||||
logger.debug("editing mixdown from JamTrackStore", mixdown)
|
||||
index = null
|
||||
for matchMixdown, i in @jamTrack.mixdowns
|
||||
if mixdown.id == matchMixdown.id
|
||||
index = i
|
||||
if index?
|
||||
@jamTrack.mixdowns[index] = mixdown
|
||||
|
||||
@changed()
|
||||
else
|
||||
logger.warn("unable to find mixdown to edit in JamTrackStore", mixdown)
|
||||
else
|
||||
logger.warn("no jamtrack to edit mixdown for in JamTrackStore", mixdown)
|
||||
|
||||
addOrUpdatePackage: (mixdown_package) ->
|
||||
if @jamTrack?
|
||||
added = false
|
||||
|
|
@ -237,5 +460,50 @@ JamTrackActions = @JamTrackActions
|
|||
else
|
||||
logger.warn("no mixdown to add package to in JamTrackStore", mixdown_package)
|
||||
|
||||
|
||||
updateDownloadProgress: () ->
|
||||
|
||||
if @bytesReceived? and @bytesTotal?
|
||||
progress = "#{Math.round(@bytesReceived/@bytesTotal * 100)}%"
|
||||
else
|
||||
progress = '0%'
|
||||
|
||||
#@root.find('.state-downloading .progress').text(progress)
|
||||
|
||||
downloadProgressCallback: (bytesReceived, bytesTotal) ->
|
||||
logger.debug("download #{bytesReceived}/#{bytesTotal}")
|
||||
|
||||
@bytesReceived = Number(bytesReceived)
|
||||
@bytesTotal = Number(bytesTotal)
|
||||
|
||||
# the reason this timeout is set is because, without it,
|
||||
# we observe that the client will hang. So, if you remove this timeout, make sure to test with real client
|
||||
setTimeout(this.updateDownloadProgress, 100)
|
||||
|
||||
downloadSuccessCallback: (updateLocation) ->
|
||||
# is the package loadable yet?
|
||||
logger.debug("JamTrackStore: download complete - on to keying")
|
||||
@attemptKeying()
|
||||
@changed()
|
||||
|
||||
downloadFailureCallback: (errorMsg) ->
|
||||
|
||||
if @jamTrack?.activeMixdown?
|
||||
@jamTrack.activeMixdown.client_state = 'download_fail'
|
||||
@changed()
|
||||
|
||||
# makes a function name for the backend
|
||||
makeDownloadProgressCallback: () ->
|
||||
"JamTrackStore.downloadProgressCallback"
|
||||
|
||||
# makes a function name for the backend
|
||||
makeDownloadSuccessCallback: () ->
|
||||
"JamTrackStore.downloadSuccessCallback"
|
||||
|
||||
# makes a function name for the backend
|
||||
makeDownloadFailureCallback: () ->
|
||||
"JamTrackStore.downloadFailureCallback"
|
||||
|
||||
|
||||
}
|
||||
)
|
||||
|
|
@ -53,6 +53,11 @@ VideoActions = @VideoActions
|
|||
RecordingActions.initModel(@recordingModel)
|
||||
@helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack)
|
||||
|
||||
onMixdownActive: (mixdown) ->
|
||||
if @currentSession?.jam_track?
|
||||
@currentSession.jam_track.mixdown = mixdown
|
||||
@issueChange()
|
||||
|
||||
|
||||
onVideoChanged: (@videoState) ->
|
||||
|
||||
|
|
@ -241,6 +246,7 @@ VideoActions = @VideoActions
|
|||
|
||||
rest.closeJamTrack({id: @currentSessionId})
|
||||
.done(() =>
|
||||
@downloadingJamTrack = false
|
||||
@refreshCurrentSession(true)
|
||||
)
|
||||
.fail((jqXHR) =>
|
||||
|
|
|
|||
|
|
@ -55,11 +55,29 @@ body.media-controls-popup.popup {
|
|||
margin-top:15px;
|
||||
font-size:12px;
|
||||
font-weight:normal;
|
||||
|
||||
span {
|
||||
vertical-align:middle;
|
||||
}
|
||||
img {
|
||||
vertical-align:middle;
|
||||
margin-left:5px;
|
||||
height:16px;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size:12px;
|
||||
font-weight:normal;
|
||||
|
||||
span {
|
||||
vertical-align:middle;
|
||||
}
|
||||
img {
|
||||
vertical-align:middle;
|
||||
margin-left:5px;
|
||||
height:16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,6 +123,7 @@ body.media-controls-popup.popup {
|
|||
background-color:#2c2c2c;
|
||||
@include border_box_sizing;
|
||||
border-spacing:7px;
|
||||
text-align: left;
|
||||
|
||||
&.active {
|
||||
background-color:#44423f;
|
||||
|
|
|
|||
|
|
@ -18,22 +18,27 @@ class ApiJamTrackMixdownsController < ApiController
|
|||
end
|
||||
|
||||
def show
|
||||
JamTrack.find()
|
||||
@jam_track_mixdown = JamTrackMixdown.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
def delete
|
||||
@jam_track_mixdown = JamTrackMixdown.find(params[:id])
|
||||
@jam_track_mixdown.name = params[:name] if params[:name]
|
||||
@jam_track_mixdown.description = params[:description] if params[:description]
|
||||
@jam_track_mixdown.save
|
||||
@jam_track_mixdown.destroy
|
||||
render json: {}, status:204
|
||||
end
|
||||
|
||||
def update
|
||||
@mixdown = JamTrackMixdown.find(params[:id])
|
||||
@mixdown.name = params[:name] if params[:name]
|
||||
@mixdown.description = params[:description] if params[:description]
|
||||
@mixdown.save
|
||||
if params[:active]
|
||||
@jam_track_right.last_mixdown = @jam_track_mixdown
|
||||
@jam_track_right.last_mixdown = @mixdown
|
||||
@jam_track_right.save
|
||||
end
|
||||
|
||||
if @jam_track_mixdown.errors.any?
|
||||
respond_with_model(@jam_track_mixdown)
|
||||
if @mixdown.errors.any?
|
||||
respond_with_model(@mixdown)
|
||||
return
|
||||
else
|
||||
|
||||
|
|
|
|||
|
|
@ -153,7 +153,10 @@ class ApiJamTracksController < ApiController
|
|||
end
|
||||
|
||||
def keys
|
||||
puts "Keys"
|
||||
puts "--------------------------"
|
||||
jamtrack_holder = params[:jamtracks]
|
||||
puts jamtrack_holder.inspect
|
||||
|
||||
unless jamtrack_holder.kind_of?(Hash)
|
||||
render :json => {message: 'jamtracks parameter must be an hash'}, :status => 422
|
||||
|
|
@ -169,20 +172,49 @@ class ApiJamTracksController < ApiController
|
|||
|
||||
|
||||
# jamtracks come in the form id-44 or id-48, so we need to do a little extra parsing
|
||||
# mixdowns come in the form id_mixid-44 or id_mixid-48, so we also need to handle that
|
||||
|
||||
jamtrack_ids = Set.new
|
||||
jamtracks_fq_ids = Set.new
|
||||
jamtrack_mixdowns = {}
|
||||
|
||||
jamtracks.each do |jamtrack|
|
||||
rindex = jamtrack.rindex('-')
|
||||
if rindex
|
||||
id = jamtrack[0..(rindex-1)]
|
||||
jamtrack_ids << id
|
||||
|
||||
# let's see if a mixid is in this ID
|
||||
rindex = id.rindex('_')
|
||||
|
||||
if rindex
|
||||
# ok, this is id_mixid-44 format; so we need to parse again for the ID
|
||||
just_id = jamtrack[0..(rindex-1)]
|
||||
sample_rate = jamtrack[-2..-1]
|
||||
|
||||
jamtrack_ids << just_id
|
||||
|
||||
simulated_fq_id = "#{just_id}-#{sample_rate}"
|
||||
mixdown_info = jamtrack_mixdowns[simulated_fq_id]
|
||||
|
||||
unless mixdown_info
|
||||
mixdown_info = []
|
||||
jamtrack_mixdowns[simulated_fq_id] = mixdown_info
|
||||
end
|
||||
mixdown_info << id
|
||||
|
||||
else
|
||||
jamtrack_ids << id
|
||||
end
|
||||
|
||||
|
||||
jamtracks_fq_ids << jamtrack # includes sample rate
|
||||
end
|
||||
end
|
||||
|
||||
@jam_tracks = JamTrackRight.list_keys(current_user, jamtrack_ids)
|
||||
@jamtracks_fq_ids = jamtracks_fq_ids
|
||||
@jamtrack_mixdowns = jamtrack_mixdowns
|
||||
puts "jamtrack_mixdowns #{jamtrack_mixdowns}"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
object @package
|
||||
|
||||
attributes :id, :jam_track_mixdown_id, :file_type, :sample_rate, :encrypt_type, :error_count, :error_reason, :error_detail, :signing_state, :packaging_steps, :current_packaging_step
|
||||
attributes :id, :jam_track_mixdown_id, :file_type, :sample_rate, :encrypt_type, :error_count, :error_reason, :error_detail, :signing_state, :packaging_steps, :current_packaging_step, :version
|
||||
|
|
|
|||
|
|
@ -17,7 +17,35 @@ node do |jam_track|
|
|||
private: jam_track['private_key_48'],
|
||||
error: jam_track['private_key_48'] ? nil : ( jam_track['jam_track_right_id'] ? 'no_key' : 'not_purchased' )
|
||||
}
|
||||
end
|
||||
|
||||
# now include mixdown info
|
||||
mixdowns_44 = []
|
||||
mixdown_info = @jamtrack_mixdowns[id]
|
||||
if mixdown_info
|
||||
mixdown_info.each do |mixdown_id|
|
||||
mixdowns_44 << {
|
||||
id: mixdown_id + '-44',
|
||||
private: jam_track['private_key_44'],
|
||||
error: jam_track['private_key_44'] ? nil : ( jam_track['jam_track_right_id'] ? 'no_key' : 'not_purchased' )
|
||||
}
|
||||
end
|
||||
end
|
||||
result['mixdowns_44'] = mixdowns_44
|
||||
|
||||
# now include mixdown info
|
||||
mixdowns_48 = []
|
||||
mixdown_info = @jamtrack_mixdowns[id + '-48']
|
||||
if mixdown_info
|
||||
mixdown_info.each do |mixdown_id|
|
||||
mixdowns_48 << {
|
||||
id: mixdown_id + '-48',
|
||||
private: jam_track['private_key_48'],
|
||||
error: jam_track['private_key_48'] ? nil : ( jam_track['jam_track_right_id'] ? 'no_key' : 'not_purchased' )
|
||||
}
|
||||
end
|
||||
end
|
||||
result['mixdowns_48'] = mixdowns_48
|
||||
|
||||
result
|
||||
end
|
||||
|
|
@ -81,6 +81,12 @@ else
|
|||
child({:jam_track => :jam_track}, :if => lambda { |music_session| music_session.users.exists?(current_user) }) {
|
||||
attributes :id, :name, :description
|
||||
|
||||
node :mixdown do |jam_track|
|
||||
right = jam_track.right_for_user(User.find(@music_session.jam_track_initiator_id))
|
||||
|
||||
{id: right ? right.last_mixdown_id : nil}
|
||||
end
|
||||
|
||||
child(:jam_track_tracks => :tracks) {
|
||||
attributes :id, :part, :instrument, :track_type
|
||||
}
|
||||
|
|
|
|||
|
|
@ -349,4 +349,7 @@ script type="text/template" id="template-help-ftue-video-disable"
|
|||
li If you know you never want to see anyone else's video.
|
||||
li If you are experiencing technical problems with others send you video.
|
||||
|
||||
script type="text/template" id="template-help-no-change-while-loading"
|
||||
span Certain actions are disabled while a track is being loaded.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -257,6 +257,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/mixdowns/:id' => 'api_jam_track_mixdowns#show', :via => :get
|
||||
match '/mixdowns/:id' => 'api_jam_track_mixdowns#update', :via => :post
|
||||
match '/mixdowns' => 'api_jam_track_mixdowns#create', :via => :post
|
||||
match '/mixdowns/:id' => 'api_jam_track_mixdowns#delete', :via => :delete
|
||||
match '/mixdown_packages/:id' => 'api_jam_track_mixdowns#show_package', :via => :get
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue