Merge with latest develop
This commit is contained in:
commit
4c4121e4d7
|
|
@ -285,4 +285,5 @@ musician_search.sql
|
|||
signup_hints.sql
|
||||
packaging_notices.sql
|
||||
first_played_jamtrack_at.sql
|
||||
payment_history.sql
|
||||
payment_history.sql
|
||||
jam_track_right_private_key.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
ALTER TABLE jam_track_rights ADD COLUMN private_key_44 VARCHAR;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN private_key_48 VARCHAR;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN signed_48 BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN signed_44 BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE jam_track_rights DROP COLUMN private_key;
|
||||
ALTER TABLE jam_track_rights DROP COLUMN signed;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN signing_started_at_44 TIMESTAMP;
|
||||
ALTER TABLE jam_track_rights ADD COLUMN signing_started_at_48 TIMESTAMP;
|
||||
ALTER TABLE jam_track_rights DROP COLUMN signing_started_at;
|
||||
|
||||
|
||||
|
|
@ -23,6 +23,6 @@ class JamTrackRightUploader < CarrierWave::Uploader::Base
|
|||
end
|
||||
|
||||
def filename
|
||||
"#{model.store_dir}/#{model.filename}" if model.id
|
||||
"#{model.store_dir}/#{model.filename(mounted_as)}" if model.id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -82,10 +82,18 @@ module JamRuby
|
|||
else
|
||||
jam_track_right.url_44.store!(File.open(output_jkz, "rb"))
|
||||
end
|
||||
|
||||
jam_track_right.signed=true
|
||||
jam_track_right.downloaded_since_sign=false
|
||||
jam_track_right.private_key=File.read("#{tmp_dir}/skey.pem")
|
||||
|
||||
if sample_rate == 48
|
||||
jam_track_right.signed_48 = true
|
||||
jam_track_right.private_key_48 = File.read("#{tmp_dir}/skey.pem")
|
||||
else
|
||||
jam_track_right.signed_44 = true
|
||||
jam_track_right.private_key_44 = File.read("#{tmp_dir}/skey.pem")
|
||||
end
|
||||
|
||||
jam_track_right.signing_queued_at = nil # if left set, throws off signing_state on subsequent signing attempts
|
||||
jam_track_right.downloaded_since_sign = false
|
||||
|
||||
jam_track_right.save!
|
||||
end
|
||||
end # mktmpdir
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ module JamRuby
|
|||
# try to catch major transitions:
|
||||
|
||||
# if just queue time changes, start time changes, or signed time changes, send out a notice
|
||||
if signing_queued_at_was != signing_queued_at || signing_started_at_was != signing_started_at || last_signed_at_was != last_signed_at || current_packaging_step != current_packaging_step_was || packaging_steps != packaging_steps_was
|
||||
if signing_queued_at_was != signing_queued_at || signing_started_at_48_was != signing_started_at_48 || signing_started_at_44_was != signing_started_at_44 || last_signed_at_was != last_signed_at || current_packaging_step != current_packaging_step_was || packaging_steps != packaging_steps_was
|
||||
SubscriptionMessage.jam_track_signing_job_change(self)
|
||||
end
|
||||
end
|
||||
|
|
@ -39,8 +39,8 @@ module JamRuby
|
|||
end
|
||||
|
||||
# create name of the file
|
||||
def filename
|
||||
"#{jam_track.name}.jkz"
|
||||
def filename(bitrate)
|
||||
"#{jam_track.name}-#{bitrate == :url_48 ? '48' : '44'}.jkz"
|
||||
end
|
||||
|
||||
def verify_download_count
|
||||
|
|
@ -71,11 +71,12 @@ module JamRuby
|
|||
if bitrate==48
|
||||
self.length_48 = length
|
||||
self.md5_48 = md5
|
||||
self.signed_48 = true
|
||||
else
|
||||
self.length_44 = length
|
||||
self.md5_44 = md5
|
||||
self.signed_44 = true
|
||||
end
|
||||
self.signed = true
|
||||
self.error_count = 0
|
||||
self.error_reason = nil
|
||||
self.error_detail = nil
|
||||
|
|
@ -104,7 +105,7 @@ module JamRuby
|
|||
|
||||
def enqueue(sample_rate=48)
|
||||
begin
|
||||
JamTrackRight.where(:id => self.id).update_all(:signing_queued_at => Time.now, :signing_started_at => nil, :last_signed_at => nil)
|
||||
JamTrackRight.where(:id => self.id).update_all(:signing_queued_at => Time.now, :signing_started_at_44 => nil, :signing_started_at_48 => nil, :last_signed_at => nil)
|
||||
Resque.enqueue(JamTracksBuilder, self.id, sample_rate)
|
||||
true
|
||||
rescue Exception => e
|
||||
|
|
@ -116,7 +117,7 @@ module JamRuby
|
|||
|
||||
# if the job is already signed, just queued up for signing, or currently signing, then don't enqueue... otherwise fire it off
|
||||
def enqueue_if_needed(sample_rate=48)
|
||||
state = signing_state
|
||||
state = signing_state(sample_rate)
|
||||
if state == 'SIGNED' || state == 'SIGNING' || state == 'QUEUED'
|
||||
false
|
||||
else
|
||||
|
|
@ -129,9 +130,9 @@ module JamRuby
|
|||
# @return true if signed && file exists for the sample_rate specifed:
|
||||
def ready?(sample_rate=48)
|
||||
if sample_rate==48
|
||||
self.signed && self.url_48.present? && self.url_48.file.exists?
|
||||
self.signed_48 && self.url_48.present? && self.url_48.file.exists?
|
||||
else
|
||||
self.signed && self.url_44.present? && self.url_44.file.exists?
|
||||
self.signed_44 && self.url_44.present? && self.url_44.file.exists?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -143,8 +144,20 @@ module JamRuby
|
|||
# QUEUED_TIMEOUT - the package signing job (JamTrackBuilder) was queued, but never executed
|
||||
# QUEUED - the package is queued to sign
|
||||
# QUIET - the jam_track_right exists, but no job has been kicked off; a job needs to be enqueued
|
||||
def signing_state
|
||||
def signing_state(sample_rate = nil)
|
||||
state = nil
|
||||
|
||||
# if the caller did not specified sample rate, we will determine what signing state to check by looking at the most recent signing attempt
|
||||
if sample_rate.nil?
|
||||
# determine what package is being signed by checking the most recent signing_started at
|
||||
time_48 = signing_started_at_48.to_i
|
||||
time_44 = signing_started_at_44.to_i
|
||||
sample_rate = time_48 > time_44 ? 48 : 44
|
||||
end
|
||||
|
||||
signed = sample_rate == 48 ? signed_48 : signed_44
|
||||
signing_started_at = sample_rate == 48 ? signing_started_at_48 : signing_started_at_44
|
||||
|
||||
if signed
|
||||
state = 'SIGNED'
|
||||
elsif signing_started_at
|
||||
|
|
@ -170,11 +183,16 @@ module JamRuby
|
|||
end
|
||||
state
|
||||
end
|
||||
|
||||
def signed?(sample_rate)
|
||||
sample_rate == 48 ? signed_48 : signed_44
|
||||
end
|
||||
|
||||
def update_download_count(count=1)
|
||||
self.download_count = self.download_count + count
|
||||
self.last_downloaded_at = Time.now
|
||||
|
||||
if self.signed
|
||||
if self.signed_44 || self.signed_48
|
||||
self.downloaded_since_sign = true
|
||||
end
|
||||
end
|
||||
|
|
@ -184,7 +202,7 @@ module JamRuby
|
|||
return []
|
||||
end
|
||||
|
||||
JamTrack.select('jam_tracks.id, jam_track_rights.private_key AS private_key, jam_track_rights.id AS jam_track_right_id')
|
||||
JamTrack.select('jam_tracks.id, jam_track_rights.private_key_44 AS private_key_44, jam_track_rights.private_key_48 AS private_key_48, jam_track_rights.id AS jam_track_right_id')
|
||||
.joins("LEFT OUTER JOIN jam_track_rights ON jam_tracks.id = jam_track_rights.jam_track_id AND jam_track_rights.user_id = '#{user.id}'")
|
||||
.where('jam_tracks.id IN (?)', jamtracks)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ module JamRuby
|
|||
@jam_track_right = JamTrackRight.find(jam_track_right_id)
|
||||
|
||||
# bailout check
|
||||
if @jam_track_right.signed
|
||||
if @jam_track_right.signed?(bitrate)
|
||||
log.debug("package is already signed. bailing")
|
||||
return
|
||||
end
|
||||
|
|
@ -39,12 +39,13 @@ module JamRuby
|
|||
|
||||
# track that it's started ( and avoid db validations )
|
||||
signing_started_at = Time.now
|
||||
signing_started_model_symbol = bitrate == 48 ? :signing_started_at_48 : :signing_started_at_44
|
||||
last_step_at = Time.now
|
||||
JamTrackRight.where(:id => @jam_track_right.id).update_all(:signing_started_at => signing_started_at, :should_retry => false, packaging_steps: total_steps, current_packaging_step: 0, last_step_at: last_step_at)
|
||||
# because we are skiping after_save, we have to keep the model current for the notification. A bit ugly...
|
||||
JamTrackRight.where(:id => @jam_track_right.id).update_all(signing_started_model_symbol => signing_started_at, :should_retry => false, packaging_steps: total_steps, current_packaging_step: 0, last_step_at: last_step_at)
|
||||
# because we are skipping 'after_save', we have to keep the model current for the notification. A bit ugly...
|
||||
@jam_track_right.current_packaging_step = 0
|
||||
@jam_track_right.packaging_steps = total_steps
|
||||
@jam_track_right.signing_started_at = signing_started_at
|
||||
@jam_track_right[signing_started_model_symbol] = signing_started_at
|
||||
@jam_track_right.should_retry = false
|
||||
@jam_track_right.last_step_at = Time.now
|
||||
SubscriptionMessage.jam_track_signing_job_change(@jam_track_right)
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ describe JamTrackRight do
|
|||
JamRuby::JamTracksManager.save_jam_track_jkz(user, jam_track)
|
||||
#}.to_not raise_error(ArgumentError)
|
||||
jam_track_right.reload
|
||||
jam_track_right[:url_48].should == jam_track_right.store_dir + '/' + jam_track_right.filename
|
||||
jam_track_right[:url_48].should == jam_track_right.store_dir + '/' + jam_track_right.filename(:url_48)
|
||||
|
||||
# verify it's on S3
|
||||
url = jam_track_right[:url_48]
|
||||
|
|
@ -109,11 +109,12 @@ describe JamTrackRight do
|
|||
end
|
||||
|
||||
it "valid track with rights to it by querying user" do
|
||||
jam_track_right = FactoryGirl.create(:jam_track_right, private_key: 'keyabc')
|
||||
jam_track_right = FactoryGirl.create(:jam_track_right, private_key_44: 'keyabc')
|
||||
keys = JamTrackRight.list_keys(jam_track_right.user, [jam_track_right.jam_track.id])
|
||||
keys.should have(1).items
|
||||
keys[0].id.should == jam_track_right.jam_track.id
|
||||
keys[0]['private_key'].should eq('keyabc')
|
||||
keys[0]['private_key_44'].should eq('keyabc')
|
||||
keys[0]['private_key_48'].should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -124,7 +125,7 @@ describe JamTrackRight do
|
|||
end
|
||||
|
||||
it "signed" do
|
||||
right = FactoryGirl.create(:jam_track_right, signed: true)
|
||||
right = FactoryGirl.create(:jam_track_right, signed_44: true, signing_started_at_44: Time.now)
|
||||
right.signing_state.should eq('SIGNED')
|
||||
end
|
||||
|
||||
|
|
@ -134,23 +135,23 @@ describe JamTrackRight do
|
|||
end
|
||||
|
||||
it "signing" do
|
||||
right = FactoryGirl.create(:jam_track_right, signing_started_at: Time.now, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
right.signing_state.should eq('SIGNING')
|
||||
right = FactoryGirl.create(:jam_track_right, signing_started_at_44: Time.now, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
right.signing_state(44).should eq('SIGNING')
|
||||
end
|
||||
|
||||
it "signing timeout" do
|
||||
right = FactoryGirl.create(:jam_track_right, signing_started_at: Time.now - 100, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
right.signing_state.should eq('SIGNING_TIMEOUT')
|
||||
right = FactoryGirl.create(:jam_track_right, signing_started_at_48: Time.now - 100, packaging_steps: 3, current_packaging_step:0, last_step_at:Time.now)
|
||||
right.signing_state(48).should eq('SIGNING_TIMEOUT')
|
||||
end
|
||||
|
||||
it "queued" do
|
||||
right = FactoryGirl.create(:jam_track_right, signing_queued_at: Time.now)
|
||||
right.signing_state.should eq('QUEUED')
|
||||
right.signing_state(44).should eq('QUEUED')
|
||||
end
|
||||
|
||||
it "signing timeout" do
|
||||
right = FactoryGirl.create(:jam_track_right, signing_queued_at: Time.now - (APP_CONFIG.signing_job_queue_max_time + 1))
|
||||
right.signing_state.should eq('QUEUED_TIMEOUT')
|
||||
right.signing_state(44).should eq('QUEUED_TIMEOUT')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,13 @@ describe JamTracksBuilder do
|
|||
jam_track_right[:url_44].should be_nil
|
||||
JamTracksBuilder.perform(jam_track_right.id, 48)
|
||||
jam_track_right.reload
|
||||
jam_track_right[:url_48].should == jam_track_right.store_dir + '/' + jam_track_right.filename
|
||||
jam_track_right[:url_48].should == jam_track_right.store_dir + '/' + jam_track_right.filename(:url_48)
|
||||
jam_track_track[:url_44].should be_nil
|
||||
|
||||
jam_track_right.signed_48.should be_true
|
||||
jam_track_right.signing_started_at_48.should_not be_nil
|
||||
jam_track_right.signed_44.should be_false
|
||||
jam_track_right.signing_started_at_44.should be_nil
|
||||
end
|
||||
|
||||
describe "with bitrate 44" do
|
||||
|
|
@ -76,9 +81,14 @@ describe JamTracksBuilder do
|
|||
jam_track_right[:url_48].should be_nil
|
||||
JamTracksBuilder.perform(jam_track_right.id, 44)
|
||||
jam_track_right.reload
|
||||
jam_track_right[:url_44].should == jam_track_right.store_dir + '/' + jam_track_right.filename
|
||||
jam_track_right[:url_44].should == jam_track_right.store_dir + '/' + jam_track_right.filename(:url_44)
|
||||
jam_track_right.url_44.should_not be_nil
|
||||
jam_track_track[:url_48].should be_nil
|
||||
|
||||
jam_track_right.signed_44.should be_true
|
||||
jam_track_right.signing_started_at_44.should_not be_nil
|
||||
jam_track_right.signed_48.should be_false
|
||||
jam_track_right.signing_started_at_48.should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -23,14 +23,14 @@ describe JamTracksCleaner do
|
|||
|
||||
it "should clean" do
|
||||
jam_track_right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track)
|
||||
jam_track_right.signed=true
|
||||
jam_track_right.signed_48=true
|
||||
jam_track_right
|
||||
|
||||
jam_track_right.url_48.store!(File.open(RIGHT_NAME))
|
||||
jam_track_right.downloaded_since_sign=true
|
||||
jam_track_right.save!
|
||||
|
||||
jam_track_right[:url_48].should == jam_track_right.store_dir + '/' + jam_track_right.filename
|
||||
jam_track_right[:url_48].should == jam_track_right.store_dir + '/' + jam_track_right.filename(:url_48)
|
||||
jam_track_right.reload
|
||||
|
||||
# Should exist after uploading:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
var rest = context.JK.Rest();
|
||||
var userId;
|
||||
var user = {};
|
||||
|
||||
var gearUtils = context.JK.GearUtilsInstance;
|
||||
|
||||
function beforeShow(data) {
|
||||
console.log("beforeShow", data)
|
||||
|
|
@ -90,7 +90,11 @@
|
|||
var delimiter = ", ";
|
||||
if (profileMap && profileMap.length > 0) {
|
||||
$.each(profileMap, function(index, val) {
|
||||
profiles += val.name + delimiter;
|
||||
var inputName = val.name;
|
||||
if (inputName == gearUtils.JAMKAZAM_VIRTUAL_INPUT) {
|
||||
inputName = gearUtils.SYSTEM_DEFAULT_PLAYBACK_ONLY;
|
||||
}
|
||||
profiles += inputName + delimiter;
|
||||
});
|
||||
|
||||
return profiles.substring(0, profiles.length - delimiter.length);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,10 @@
|
|||
|
||||
logger.debug("alert callback", type, text);
|
||||
|
||||
var alertData = ALERT_TYPES[type];
|
||||
var alertData = $.extend({}, ALERT_TYPES[type]);
|
||||
|
||||
alertData.text = text;
|
||||
|
||||
if(alertData) {
|
||||
$document.triggerHandler(alertData.name, alertData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
var $templateOpenJamTrackRow = null;
|
||||
var $downloadedTrackHelp = null;
|
||||
var $whatAreJamTracks = null;
|
||||
var sampleRate = null;
|
||||
var sampleRateForFilename = null;
|
||||
|
||||
|
||||
function emptyList() {
|
||||
|
|
@ -24,18 +26,25 @@
|
|||
}
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
}
|
||||
|
||||
function afterShow() {
|
||||
$dialog.data('result', null)
|
||||
emptyList();
|
||||
resetPagination();
|
||||
showing = true;
|
||||
sampleRate = context.jamClient.GetSampleRate()
|
||||
sampleRateForFilename = sampleRate == 48 ? '48' : '44';
|
||||
|
||||
getPurchasedJamTracks(0)
|
||||
.done(function(data, textStatus, jqXHR) {
|
||||
// initialize pagination
|
||||
var $paginator = context.JK.Paginator.create(parseInt(jqXHR.getResponseHeader('total-entries')), perPage, 0, onPageSelected)
|
||||
$paginatorHolder.append($paginator);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
function afterHide() {
|
||||
showing = false;
|
||||
}
|
||||
|
|
@ -58,7 +67,7 @@
|
|||
options.jamTrackId = jamTrack.id;
|
||||
options.name = jamTrack.name;
|
||||
options.artist = jamTrack.original_artist;
|
||||
var detail = context.jamClient.JamTrackGetTrackDetail(jamTrack.id) || {}
|
||||
var detail = context.jamClient.JamTrackGetTrackDetail(jamTrack.id + '-' + sampleRateForFilename) || {}
|
||||
options.downloaded = detail.key_state == 'ready' ? 'Yes' : 'No'
|
||||
|
||||
var $tr = $(context._.template($templateOpenJamTrackRow.html(), options, { variable: 'data' }));
|
||||
|
|
@ -99,6 +108,7 @@
|
|||
function initialize(){
|
||||
var dialogBindings = {
|
||||
'beforeShow' : beforeShow,
|
||||
'afterShow' : afterShow,
|
||||
'afterHide': afterHide
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,10 @@
|
|||
context.jamClient.ClosePreviewRecording();
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function discardRecording(e) {
|
||||
|
||||
resetForm();
|
||||
|
|
@ -323,7 +327,8 @@
|
|||
function initialize() {
|
||||
var dialogBindings = {
|
||||
'beforeShow': beforeShow,
|
||||
'afterHide': afterHide
|
||||
'afterHide': afterHide,
|
||||
'onCancel': onCancel
|
||||
};
|
||||
|
||||
app.bindDialog('recordingFinished', dialogBindings);
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
|
||||
showInitial: () =>
|
||||
@logger.debug("showing #{@state.name}")
|
||||
@sampleRate = context.jamClient.GetSampleRate()
|
||||
@sampleRateForFilename = if @sampleRate == 48 then '48' else '44'
|
||||
@attempts = @attempts + 1
|
||||
this.expectTransition()
|
||||
context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent)
|
||||
|
|
@ -350,17 +352,18 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
|
||||
checkState: () =>
|
||||
# check for the success state against the local state of the client... if it's playable, then we should be OK
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (@jamTrack.id)
|
||||
fqId = "#{@jamTrack.id}-#{@sampleRateForFilename}"
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId)
|
||||
|
||||
@logger.debug("DownloadJamTrack: JamTrackGetTrackDetail.key_state: " + @trackDetail.key_state)
|
||||
@logger.debug("DownloadJamTrack: JamTrackGetTrackDetail(#{fqId}).key_state: " + @trackDetail.key_state, @trackDetail)
|
||||
|
||||
# first check if the version is not the same; if so, invalidate.
|
||||
|
||||
if @trackDetail.version?
|
||||
if @jamTrack.version != @trackDetail.version
|
||||
@logger.info("DownloadJamTrack: JamTrack on disk is different version (stored: #{@trackDetail.version}, server: #{@jamTrack.version}. Invalidating")
|
||||
context.jamClient.InvalidateJamTrack(@jamTrack.id)
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (@jamTrack.id)
|
||||
context.jamClient.InvalidateJamTrack("#{@jamTrack.id}-#{@sampleRateForFilename}")
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail ("#{@jamTrack.id}-#{@sampleRateForFilename}")
|
||||
|
||||
if @trackDetail.version?
|
||||
@logger.error("after invalidating package, the version is still wrong!")
|
||||
|
|
@ -447,9 +450,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
@attemptedEnqueue = true
|
||||
@ajaxEnqueueAborted = false
|
||||
|
||||
sampleRate = context.jamClient.GetSampleRate()
|
||||
|
||||
@rest.enqueueJamTrack({id: @jamTrack.id, sample_rate: sampleRate})
|
||||
@rest.enqueueJamTrack({id: @jamTrack.id, sample_rate: @sampleRate})
|
||||
.done(this.processEnqueueJamTrack)
|
||||
.fail(this.processEnqueueJamTrackFail)
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@
|
|||
}
|
||||
function FTUESetMusicProfileName() {
|
||||
|
||||
}
|
||||
|
||||
function FTUESetPreferredMixerSampleRate() {
|
||||
|
||||
}
|
||||
|
||||
function FTUESelectVideoCaptureDevice(device, settings) {
|
||||
|
|
@ -1040,6 +1044,7 @@
|
|||
this.FTUEPageLeave = FTUEPageLeave;
|
||||
this.FTUEGetMusicProfileName = FTUEGetMusicProfileName;
|
||||
this.FTUESetMusicProfileName = FTUESetMusicProfileName;
|
||||
this.FTUESetPreferredMixerSampleRate = FTUESetPreferredMixerSampleRate;
|
||||
this.FTUEGetInputLatency = FTUEGetInputLatency;
|
||||
this.FTUEGetInputVolume = FTUEGetInputVolume;
|
||||
this.FTUEGetMusicInputs = FTUEGetMusicInputs;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
var playbackMode = PlaybackMode.EveryWhere;
|
||||
var monitorPlaybackTimeout = null;
|
||||
var playbackMonitorMode = PLAYBACK_MONITOR_MODE.MEDIA_FILE;
|
||||
var monitoring = false;
|
||||
|
||||
function init() {
|
||||
updateSliderPosition(0);
|
||||
|
|
@ -210,6 +211,9 @@
|
|||
}
|
||||
}
|
||||
function monitorRecordingPlayback() {
|
||||
if(!monitoring) {
|
||||
return;
|
||||
}
|
||||
if(playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK) {
|
||||
var positionMs = context.jamClient.SessionCurrrentJamTrackPlayPosMs();
|
||||
var duration = context.jamClient.SessionGetJamTracksPlayDurationMs();
|
||||
|
|
@ -262,7 +266,7 @@
|
|||
}
|
||||
|
||||
// at the end of the play, the duration sets to 0, as does currentTime. but isPlaying does not reset to
|
||||
//logger.debug("currentTimeMs, durationTimeMs, mode", currentTimeMs, durationTimeMs, playbackMonitorMode);
|
||||
logger.debug("currentTimeMs, durationTimeMs, mode", currentTimeMs, durationTimeMs, playbackMonitorMode);
|
||||
if(currentTimeMs == 0 && seenActivity) {
|
||||
if(playbackPlaying) {
|
||||
isPlaying = false;
|
||||
|
|
@ -355,7 +359,7 @@
|
|||
}
|
||||
|
||||
function startMonitor(_playbackMonitorMode) {
|
||||
|
||||
monitoring = true;
|
||||
// resets everything to zero
|
||||
init();
|
||||
|
||||
|
|
@ -373,6 +377,7 @@
|
|||
}
|
||||
|
||||
function stopMonitor() {
|
||||
monitoring = false;
|
||||
logger.debug("playbackControl.stopMonitor")
|
||||
if(monitorPlaybackTimeout!= null) {
|
||||
clearTimeout(monitorPlaybackTimeout);
|
||||
|
|
|
|||
|
|
@ -932,9 +932,9 @@
|
|||
}
|
||||
|
||||
if(optionRequiresMultiplayerProfile()) {
|
||||
if(context.JK.guardAgainstSinglePlayerProfile(app).canPlay == false) {
|
||||
return false;
|
||||
}
|
||||
// if(context.JK.guardAgainstSinglePlayerProfile(app).canPlay == false) {
|
||||
// return false;
|
||||
//}
|
||||
}
|
||||
|
||||
var valid = beforeMoveStep();
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@
|
|||
var claimedRecording = null;
|
||||
var backing_track_path = null;
|
||||
var jamTrack = null;
|
||||
var musicianAccessOnJoin; // was this a private or public session when the user tried to joined?
|
||||
|
||||
var metronomeMixer = null;
|
||||
var playbackControls = null;
|
||||
|
|
@ -211,16 +212,7 @@
|
|||
rest.getSessionHistory(data.id)
|
||||
.done(function(musicSession) {
|
||||
|
||||
var singlePlayerCheckOK = true;
|
||||
// to know whether we are allowed to be in this session, we have to check if we are the creator when checking against single player functionality
|
||||
if(musicSession.user_id != context.JK.currentUserId) {
|
||||
var canPlay = context.JK.guardAgainstSinglePlayerProfile(app, function () {
|
||||
promptLeave = false;
|
||||
});
|
||||
|
||||
singlePlayerCheckOK = canPlay.canPlay;
|
||||
}
|
||||
if(singlePlayerCheckOK) {
|
||||
musicianAccessOnJoin = musicSession.musician_access;;
|
||||
|
||||
var shouldVerifyNetwork = musicSession.musician_access;
|
||||
gearUtils.guardAgainstInvalidConfiguration(app, shouldVerifyNetwork)
|
||||
|
|
@ -270,17 +262,6 @@
|
|||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
else {
|
||||
if(canPlay.dialog) {
|
||||
canPlay.dialog.one(EVENTS.DIALOG_CLOSED, function(e, data) {
|
||||
if(data.canceled) {
|
||||
promptLeave = false;
|
||||
window.location = '/client#/home'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
|
||||
|
|
@ -308,188 +289,209 @@
|
|||
|
||||
|
||||
function afterCurrentUserLoaded() {
|
||||
var sessionModel = context.JK.CurrentSessionModel;
|
||||
|
||||
$(sessionModel.recordingModel)
|
||||
// now check if the user can play in a session with others
|
||||
var deferred = new $.Deferred();
|
||||
if(musicianAccessOnJoin) {
|
||||
deferred = context.JK.guardAgainstSinglePlayerProfile(app, function () {
|
||||
promptLeave = false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
deferred.resolve();
|
||||
}
|
||||
deferred.fail(function(result) {
|
||||
if(!result.controlled_location) {
|
||||
window.location="/client#/home"
|
||||
}
|
||||
})
|
||||
.done(function() {logger.debug("user has passed all session guards")
|
||||
promptLeave = true;
|
||||
var sessionModel = context.JK.CurrentSessionModel;
|
||||
|
||||
$(sessionModel.recordingModel)
|
||||
.on('startingRecording', function(e, data) {
|
||||
displayStartingRecording();
|
||||
lockControlsforJamTrackRecording();
|
||||
displayStartingRecording();
|
||||
lockControlsforJamTrackRecording();
|
||||
})
|
||||
.on('startedRecording', function(e, data) {
|
||||
if(data.reason) {
|
||||
var reason = data.reason;
|
||||
var detail = data.detail;
|
||||
|
||||
var title = "Could Not Start Recording";
|
||||
|
||||
if(data.reason == 'client-no-response') {
|
||||
notifyWithUserInfo(title, 'did not respond to the start signal.', detail);
|
||||
}
|
||||
else if(data.reason == 'empty-recording-id') {
|
||||
app.notifyAlert(title, "No recording ID specified.");
|
||||
}
|
||||
else if(data.reason == 'missing-client') {
|
||||
notifyWithUserInfo(title, 'could not be signalled to start recording.', detail);
|
||||
}
|
||||
else if(data.reason == 'already-recording') {
|
||||
app.notifyAlert(title, 'Already recording. If this appears incorrect, try restarting JamKazam.');
|
||||
}
|
||||
else if(data.reason == 'recording-engine-unspecified') {
|
||||
notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-create-directory') {
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-create-file') {
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording file.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-sample-rate') {
|
||||
notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail);
|
||||
}
|
||||
else if(data.reason == 'rest') {
|
||||
var jqXHR = detail[0];
|
||||
app.notifyServerError(jqXHR);
|
||||
}
|
||||
else {
|
||||
notifyWithUserInfo(title, 'Error Reason: ' + reason);
|
||||
}
|
||||
displayDoneRecording();
|
||||
}
|
||||
else
|
||||
{
|
||||
displayStartedRecording();
|
||||
displayWhoCreated(data.clientId);
|
||||
lockControlsforJamTrackRecording();
|
||||
}
|
||||
})
|
||||
.on('stoppingRecording', function(e, data) {
|
||||
displayStoppingRecording(data);
|
||||
unlockControlsforJamTrackRecording();
|
||||
})
|
||||
.on('stoppedRecording', function(e, data) {
|
||||
|
||||
unlockControlsforJamTrackRecording();
|
||||
if(sessionModel.selfOpenedJamTracks()) {
|
||||
|
||||
var timeline = context.jamClient.GetJamTrackTimeline();
|
||||
|
||||
rest.addRecordingTimeline(data.recordingId, timeline)
|
||||
.fail(function(){
|
||||
app.notify(
|
||||
{ title: "Unable to Add JamTrack Volume Data",
|
||||
text: "The volume of the JamTrack will not be correct in the recorded mix." },
|
||||
null,
|
||||
true);
|
||||
})
|
||||
}
|
||||
|
||||
if(data.reason) {
|
||||
logger.warn("Recording Discarded: ", data);
|
||||
var reason = data.reason;
|
||||
var detail = data.detail;
|
||||
|
||||
var title = "Recording Discarded";
|
||||
|
||||
if(data.reason == 'client-no-response') {
|
||||
notifyWithUserInfo(title, 'did not respond to the stop signal.', detail);
|
||||
}
|
||||
else if(data.reason == 'missing-client') {
|
||||
notifyWithUserInfo(title, 'could not be signalled to stop recording.', detail);
|
||||
}
|
||||
else if(data.reason == 'empty-recording-id') {
|
||||
app.notifyAlert(title, "No recording ID specified.");
|
||||
}
|
||||
else if(data.reason == 'wrong-recording-id') {
|
||||
app.notifyAlert(title, "Wrong recording ID specified.");
|
||||
}
|
||||
else if(data.reason == 'not-recording') {
|
||||
app.notifyAlert(title, "Not currently recording.");
|
||||
}
|
||||
else if(data.reason == 'already-stopping') {
|
||||
app.notifyAlert(title, "Already stopping the current recording.");
|
||||
}
|
||||
else if(data.reason == 'start-before-stop') {
|
||||
notifyWithUserInfo(title, 'asked that we start a new recording; cancelling the current one.', detail);
|
||||
}
|
||||
else {
|
||||
app.notifyAlert(title, "Error reason: " + reason);
|
||||
}
|
||||
|
||||
displayDoneRecording();
|
||||
}
|
||||
else {
|
||||
displayDoneRecording();
|
||||
promptUserToSave(data.recordingId, timeline);
|
||||
}
|
||||
|
||||
})
|
||||
.on('abortedRecording', function(e, data) {
|
||||
if(data.reason) {
|
||||
var reason = data.reason;
|
||||
var detail = data.detail;
|
||||
|
||||
var title = "Recording Cancelled";
|
||||
var title = "Could Not Start Recording";
|
||||
|
||||
if(data.reason == 'client-no-response') {
|
||||
notifyWithUserInfo(title, 'did not respond to the start signal.', detail);
|
||||
notifyWithUserInfo(title, 'did not respond to the start signal.', detail);
|
||||
}
|
||||
else if(data.reason == 'empty-recording-id') {
|
||||
app.notifyAlert(title, "No recording ID specified.");
|
||||
}
|
||||
else if(data.reason == 'missing-client') {
|
||||
notifyWithUserInfo(title, 'could not be signalled to start recording.', detail);
|
||||
notifyWithUserInfo(title, 'could not be signalled to start recording.', detail);
|
||||
}
|
||||
else if(data.reason == 'populate-recording-info') {
|
||||
notifyWithUserInfo(title, 'could not synchronize with the server.', detail);
|
||||
else if(data.reason == 'already-recording') {
|
||||
app.notifyAlert(title, 'Already recording. If this appears incorrect, try restarting JamKazam.');
|
||||
}
|
||||
else if(data.reason == 'recording-engine-unspecified') {
|
||||
notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail);
|
||||
notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-create-directory') {
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail);
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-create-file') {
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording file.', detail);
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording file.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-sample-rate') {
|
||||
notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail);
|
||||
notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail);
|
||||
}
|
||||
else if(data.reason == 'rest') {
|
||||
var jqXHR = detail[0];
|
||||
app.notifyServerError(jqXHR);
|
||||
}
|
||||
else {
|
||||
app.notifyAlert(title, "Error reason: " + reason);
|
||||
notifyWithUserInfo(title, 'Error Reason: ' + reason);
|
||||
}
|
||||
displayDoneRecording();
|
||||
}
|
||||
else
|
||||
{
|
||||
displayStartedRecording();
|
||||
displayWhoCreated(data.clientId);
|
||||
lockControlsforJamTrackRecording();
|
||||
}
|
||||
})
|
||||
.on('stoppingRecording', function(e, data) {
|
||||
displayStoppingRecording(data);
|
||||
unlockControlsforJamTrackRecording();
|
||||
})
|
||||
.on('stoppedRecording', function(e, data) {
|
||||
|
||||
unlockControlsforJamTrackRecording();
|
||||
if(sessionModel.selfOpenedJamTracks()) {
|
||||
|
||||
var timeline = context.jamClient.GetJamTrackTimeline();
|
||||
|
||||
rest.addRecordingTimeline(data.recordingId, timeline)
|
||||
.fail(function(){
|
||||
app.notify(
|
||||
{ title: "Unable to Add JamTrack Volume Data",
|
||||
text: "The volume of the JamTrack will not be correct in the recorded mix." },
|
||||
null,
|
||||
true);
|
||||
})
|
||||
}
|
||||
|
||||
if(data.reason) {
|
||||
logger.warn("Recording Discarded: ", data);
|
||||
var reason = data.reason;
|
||||
var detail = data.detail;
|
||||
|
||||
var title = "Recording Discarded";
|
||||
|
||||
if(data.reason == 'client-no-response') {
|
||||
notifyWithUserInfo(title, 'did not respond to the stop signal.', detail);
|
||||
}
|
||||
else if(data.reason == 'missing-client') {
|
||||
notifyWithUserInfo(title, 'could not be signalled to stop recording.', detail);
|
||||
}
|
||||
else if(data.reason == 'empty-recording-id') {
|
||||
app.notifyAlert(title, "No recording ID specified.");
|
||||
}
|
||||
else if(data.reason == 'wrong-recording-id') {
|
||||
app.notifyAlert(title, "Wrong recording ID specified.");
|
||||
}
|
||||
else if(data.reason == 'not-recording') {
|
||||
app.notifyAlert(title, "Not currently recording.");
|
||||
}
|
||||
else if(data.reason == 'already-stopping') {
|
||||
app.notifyAlert(title, "Already stopping the current recording.");
|
||||
}
|
||||
else if(data.reason == 'start-before-stop') {
|
||||
notifyWithUserInfo(title, 'asked that we start a new recording; cancelling the current one.', detail);
|
||||
}
|
||||
else {
|
||||
app.notifyAlert(title, "Error reason: " + reason);
|
||||
}
|
||||
|
||||
displayDoneRecording();
|
||||
}
|
||||
else {
|
||||
displayDoneRecording();
|
||||
promptUserToSave(data.recordingId, timeline);
|
||||
}
|
||||
|
||||
})
|
||||
.on('abortedRecording', function(e, data) {
|
||||
var reason = data.reason;
|
||||
var detail = data.detail;
|
||||
|
||||
var title = "Recording Cancelled";
|
||||
|
||||
if(data.reason == 'client-no-response') {
|
||||
notifyWithUserInfo(title, 'did not respond to the start signal.', detail);
|
||||
}
|
||||
else if(data.reason == 'missing-client') {
|
||||
notifyWithUserInfo(title, 'could not be signalled to start recording.', detail);
|
||||
}
|
||||
else if(data.reason == 'populate-recording-info') {
|
||||
notifyWithUserInfo(title, 'could not synchronize with the server.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-unspecified') {
|
||||
notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-create-directory') {
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-create-file') {
|
||||
notifyWithUserInfo(title, 'had a problem creating a recording file.', detail);
|
||||
}
|
||||
else if(data.reason == 'recording-engine-sample-rate') {
|
||||
notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail);
|
||||
}
|
||||
else {
|
||||
app.notifyAlert(title, "Error reason: " + reason);
|
||||
}
|
||||
|
||||
displayDoneRecording();
|
||||
|
||||
})
|
||||
|
||||
sessionModel.subscribe('sessionScreen', sessionChanged);
|
||||
sessionModel.joinSession(sessionId)
|
||||
sessionModel.subscribe('sessionScreen', sessionChanged);
|
||||
|
||||
sessionModel.joinSession(sessionId)
|
||||
.fail(function(xhr, textStatus, errorMessage) {
|
||||
if(xhr.status == 404) {
|
||||
// we tried to join the session, but it's already gone. kick user back to join session screen
|
||||
promptLeave = false;
|
||||
context.window.location = "/client#/findSession";
|
||||
app.notify(
|
||||
{ title: "Unable to Join Session",
|
||||
text: "The session you attempted to join is over."
|
||||
},
|
||||
null,
|
||||
true);
|
||||
if(xhr.status == 404) {
|
||||
// we tried to join the session, but it's already gone. kick user back to join session screen
|
||||
promptLeave = false;
|
||||
context.window.location = "/client#/findSession";
|
||||
app.notify(
|
||||
{ title: "Unable to Join Session",
|
||||
text: "The session you attempted to join is over."
|
||||
},
|
||||
null,
|
||||
true);
|
||||
}
|
||||
else if(xhr.status == 422) {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
if(response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track") {
|
||||
app.notifyAlert("No Inputs Configured", $('<span>You will need to reconfigure your audio device.</span>'));
|
||||
}
|
||||
else if(xhr.status == 422) {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
if(response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track") {
|
||||
app.notifyAlert("No Inputs Configured", $('<span>You will need to reconfigure your audio device.</span>'));
|
||||
}
|
||||
else if(response["errors"] && response["errors"]["music_session"] && response["errors"]["music_session"][0] == ["is currently recording"]) {
|
||||
promptLeave = false;
|
||||
context.window.location = "/client#/findSession";
|
||||
app.notify( { title: "Unable to Join Session", text: "The session is currently recording." }, null, true);
|
||||
}
|
||||
else {
|
||||
app.notifyServerError(xhr, 'Unable to Join Session');
|
||||
}
|
||||
else if(response["errors"] && response["errors"]["music_session"] && response["errors"]["music_session"][0] == ["is currently recording"]) {
|
||||
promptLeave = false;
|
||||
context.window.location = "/client#/findSession";
|
||||
app.notify( { title: "Unable to Join Session", text: "The session is currently recording." }, null, true);
|
||||
}
|
||||
else {
|
||||
app.notifyServerError(xhr, 'Unable to Join Session');
|
||||
app.notifyServerError(xhr, 'Unable to Join Session');
|
||||
}
|
||||
}
|
||||
else {
|
||||
app.notifyServerError(xhr, 'Unable to Join Session');
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// not leave session but leave screen
|
||||
|
|
@ -2727,17 +2729,22 @@
|
|||
// XXX: test with this removed; it should be unnecessary
|
||||
context.jamClient.JamTrackStopPlay();
|
||||
|
||||
var sampleRate = context.jamClient.GetSampleRate()
|
||||
var sampleRateForFilename = sampleRate == 48 ? '48' : '44'
|
||||
var fqId = jamTrack.id + '-' + sampleRateForFilename
|
||||
|
||||
if(jamTrack.jmep)
|
||||
{
|
||||
logger.debug("setting jmep data")
|
||||
context.jamClient.JamTrackLoadJmep(jamTrack.id, jamTrack.jmep)
|
||||
|
||||
context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep)
|
||||
}
|
||||
else {
|
||||
logger.debug("no jmep data for jamtrack")
|
||||
}
|
||||
|
||||
// JamTrackPlay means 'load'
|
||||
var result = context.jamClient.JamTrackPlay(jamTrack.id);
|
||||
var result = context.jamClient.JamTrackPlay(fqId);
|
||||
|
||||
if(!result) {
|
||||
app.notify(
|
||||
|
|
@ -2947,13 +2954,18 @@
|
|||
}
|
||||
|
||||
function closeJamTrack() {
|
||||
logger.debug("closing recording");
|
||||
logger.debug("closing jam track");
|
||||
|
||||
if (sessionModel.recordingModel.isRecording()) {
|
||||
logger.debug("can't close jamtrack while recording")
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!sessionModel.selfOpenedJamTracks()) {
|
||||
logger.debug("can't close jamtrack if not the opener")
|
||||
return false;
|
||||
}
|
||||
|
||||
if(downloadJamTrack) {
|
||||
logger.debug("closing DownloadJamTrack widget")
|
||||
downloadJamTrack.root.remove();
|
||||
|
|
|
|||
|
|
@ -136,20 +136,19 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
if(context.JK.guardAgainstSinglePlayerProfile(app).canPlay) {
|
||||
gearUtils.guardAgainstInvalidConfiguration(app)
|
||||
.fail(function() {
|
||||
app.notify(
|
||||
{ title: "Unable to Join Session",
|
||||
text: "You can only join a session once you have working audio gear and a tested internet connection."
|
||||
});
|
||||
})
|
||||
.done(function() {
|
||||
if (successCallback) {
|
||||
successCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
gearUtils.guardAgainstInvalidConfiguration(app)
|
||||
.fail(function() {
|
||||
app.notify(
|
||||
{ title: "Unable to Join Session",
|
||||
text: "You can only join a session once you have working audio gear and a tested internet connection."
|
||||
});
|
||||
})
|
||||
.done(function() {
|
||||
if (successCallback) {
|
||||
successCallback();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
sessionUtils.joinSession = function(sessionId) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
var $content = null;
|
||||
|
||||
function beforeShow(data) {
|
||||
|
||||
clearContent();
|
||||
}
|
||||
|
||||
function afterShow(data) {
|
||||
|
|
|
|||
|
|
@ -584,6 +584,7 @@
|
|||
logger.debug("offBackendEvent: " + alertData.name + '.' + namespace, alertData)
|
||||
$(document).off(alertData.name + '.' + namespace);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads a listbox or dropdown with the values in input_array, setting the option value
|
||||
* to the id_field and the option text to text_field. It will preselect the option with
|
||||
|
|
@ -1128,70 +1129,6 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
context.JK.guardAgainstSinglePlayerProfile = function(app, beforeCallback) {
|
||||
|
||||
var canPlayWithOthers = context.JK.GearUtilsInstance.canPlayWithOthers();
|
||||
|
||||
if(!canPlayWithOthers.canPlay) {
|
||||
logger.debug("guarding against single player profile")
|
||||
|
||||
var $dialog = app.layout.showDialog('single-player-profile-dialog');
|
||||
|
||||
// so that callers can check dialog result
|
||||
canPlayWithOthers.dialog = $dialog;
|
||||
|
||||
// allow callers to take action before default behavior
|
||||
if(beforeCallback) {
|
||||
$dialog.one(EVENTS.DIALOG_CLOSED, beforeCallback);
|
||||
}
|
||||
|
||||
$dialog.one(EVENTS.DIALOG_CLOSED, function(e, data) {
|
||||
|
||||
if(!data.canceled) {
|
||||
if(data.result.choice == 'private_session') {
|
||||
var data = {
|
||||
createType: 'quick-start',
|
||||
timezone: {},
|
||||
recurring_mode: {},
|
||||
language: {},
|
||||
band: {},
|
||||
musician_access: {},
|
||||
fans_access: {},
|
||||
rsvp_slots: [],
|
||||
open_rsvps: false
|
||||
};
|
||||
|
||||
context.JK.privateSessionSettings(data)
|
||||
|
||||
context.JK.createSession(app, data)
|
||||
.done(function(response) {
|
||||
var sessionId = response.id;
|
||||
|
||||
context.JK.GA.trackSessionCount(true, true, 0);
|
||||
|
||||
// we redirect to the session screen, which handles the REST call to POST /participants.
|
||||
logger.debug("joining session screen: " + sessionId)
|
||||
context.location = '/client#/session/' + sessionId;
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
logger.debug("unable to schedule a private session")
|
||||
app.notifyServerError(jqXHR, "Unable to schedule a private session");
|
||||
})
|
||||
}
|
||||
else if(data.result.choice == 'gear_setup') {
|
||||
window.location = '/client#/account/audio'
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("unknown choice: " + data.result.choice)
|
||||
alert("unknown choice: " + data.result.choice)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return canPlayWithOthers;
|
||||
}
|
||||
|
||||
context.JK.createSession = function(app, data) {
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@
|
|||
var newProfileName = 'FTUEAttempt-' + new Date().getTime().toString();
|
||||
logger.debug("setting FTUE-prefixed profile name to: " + newProfileName);
|
||||
context.jamClient.FTUESetMusicProfileName(newProfileName);
|
||||
context.jamClient.FTUESetPreferredMixerSampleRate(1);
|
||||
context.jamClient.FTUEClearChannelAssignments();
|
||||
newSession();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,16 +10,20 @@
|
|||
var rest = new context.JK.Rest();
|
||||
context.JK.GearUtils = gearUtils;
|
||||
var logger = context.JK.logger;
|
||||
var ALERT_NAMES = context.JK.ALERT_NAMES;
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var AUDIO_DEVICE_BEHAVIOR = context.JK.AUDIO_DEVICE_BEHAVIOR;
|
||||
var EVENTS = context.JK.EVENTS;
|
||||
var SYSTEM_DEFAULT_PLAYBACK_ONLY = 'System Default (Playback Only)';
|
||||
var JAMKAZAM_VIRTUAL_INPUT = "JamKazam Virtual Input";
|
||||
|
||||
|
||||
context.JK.GearUtilsInstance = gearUtils;
|
||||
|
||||
gearUtils.SKIPPED_NETWORK_TEST = -1; // we store a negative 1 to mean that we let the user skip.
|
||||
gearUtils.SYSTEM_DEFAULT_PLAYBACK_ONLY = SYSTEM_DEFAULT_PLAYBACK_ONLY;
|
||||
gearUtils.JAMKAZAM_VIRTUAL_INPUT = JAMKAZAM_VIRTUAL_INPUT;
|
||||
|
||||
gearUtils.skippedNetworkTest = false; // we allow someone to play in session (for one client run) if it's our fault they can't network test score
|
||||
var reloadAudioTimeout = null;
|
||||
|
|
@ -30,17 +34,39 @@
|
|||
return channel.assignment == ASSIGNMENT.CHAT || channel.assignment == ASSIGNMENT.OUTPUT || channel.assignment > 0;
|
||||
}
|
||||
|
||||
|
||||
gearUtils.resyncAudio = function() {
|
||||
|
||||
function backendMixerChange (e, data) {
|
||||
|
||||
if (data.text == 'deferred') {
|
||||
context.JK.offBackendEvent(ALERT_NAMES.BACKEND_MIXER_CHANGE, 'gearUtilsResyncAudio', backendMixerChange)
|
||||
console.log("context.jamClient.FTUEGetExpectedLatency()", context.jamClient.FTUEGetExpectedLatency().latency)
|
||||
deferred.resolve();
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
var deferred = new $.Deferred();
|
||||
|
||||
context.JK.onBackendEvent(ALERT_NAMES.BACKEND_MIXER_CHANGE, 'gearUtilsResyncAudio', backendMixerChange);
|
||||
|
||||
context.jamClient.SessionAudioResync();
|
||||
|
||||
// give backend 5 seconds to timeout
|
||||
deferred.timer = setTimeout(function() {
|
||||
deferred.rejectWith('timeout');
|
||||
context.JK.offBackendEvent(ALERT_NAMES.BACKEND_MIXER_CHANGE, 'gearUtilsResyncAudio', backendMixerChange)
|
||||
}, 5000);
|
||||
|
||||
return deferred;
|
||||
}
|
||||
|
||||
|
||||
// to play with others, you have to have inputs,
|
||||
// as well have a score below 20 ms
|
||||
gearUtils.canPlayWithOthers = function(profile) {
|
||||
|
||||
if(gon.global.gear_check_reload_audio) {
|
||||
if (!context.jamClient.IsAudioStarted()) {
|
||||
context.jamClient.ReloadAudioSystem(true, true, true);
|
||||
context.jamClient.StopAudio();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var isNoInputProfile = gearUtils.isNoInputProfile(profile);
|
||||
var expectedLatency = context.jamClient.FTUEGetExpectedLatency();
|
||||
|
|
@ -182,7 +208,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (device.name == "JamKazam Virtual Input") {
|
||||
if (device.name == JAMKAZAM_VIRTUAL_INPUT) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -431,6 +457,84 @@
|
|||
return deferred;
|
||||
}
|
||||
|
||||
context.JK.guardAgainstSinglePlayerProfile = function(app, beforeCallback) {
|
||||
|
||||
var deferred = new $.Deferred();
|
||||
|
||||
var canPlayWithOthers = context.JK.GearUtilsInstance.canPlayWithOthers();
|
||||
|
||||
if(!canPlayWithOthers.canPlay) {
|
||||
logger.debug("guarding against single player profile")
|
||||
|
||||
var $dialog = app.layout.showDialog('single-player-profile-dialog');
|
||||
|
||||
// so that callers can check dialog result
|
||||
canPlayWithOthers.dialog = $dialog;
|
||||
|
||||
// allow callers to take action before default behavior
|
||||
if(beforeCallback) {
|
||||
$dialog.one(EVENTS.DIALOG_CLOSED, beforeCallback);
|
||||
}
|
||||
|
||||
$dialog.one(EVENTS.DIALOG_CLOSED, function(e, data) {
|
||||
|
||||
if(data.canceled) {
|
||||
deferred.rejectWith(canPlayWithOthers, [{ reason: 'canceled', controlled_location:false }])
|
||||
}
|
||||
else {
|
||||
if(data.result.choice == 'private_session') {
|
||||
var data = {
|
||||
createType: 'quick-start',
|
||||
timezone: {},
|
||||
recurring_mode: {},
|
||||
language: {},
|
||||
band: {},
|
||||
musician_access: {},
|
||||
fans_access: {},
|
||||
rsvp_slots: [],
|
||||
open_rsvps: false
|
||||
};
|
||||
|
||||
context.JK.privateSessionSettings(data)
|
||||
|
||||
context.JK.createSession(app, data)
|
||||
.done(function(response) {
|
||||
var sessionId = response.id;
|
||||
|
||||
context.JK.GA.trackSessionCount(true, true, 0);
|
||||
|
||||
deferred.rejectWith(canPlayWithOthers, [{ reason: 'private_session', controlled_location:true }])
|
||||
// we redirect to the session screen, which handles the REST call to POST /participants.
|
||||
logger.debug("joining session screen: " + sessionId)
|
||||
context.location = '/client#/session/' + sessionId;
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
deferred.rejectWith(canPlayWithOthers, [{ reason: 'gear_setup', controlled_location:false }])
|
||||
logger.debug("unable to schedule a private session")
|
||||
app.notifyServerError(jqXHR, "Unable to schedule a private session");
|
||||
})
|
||||
}
|
||||
else if(data.result.choice == 'gear_setup') {
|
||||
deferred.rejectWith(canPlayWithOthers, [{ reason: data.result.choice,controlled_location:true }])
|
||||
window.location = '/client#/account/audio'
|
||||
}
|
||||
else
|
||||
{
|
||||
deferred.rejectWith(canPlayWithOthers, [{ reason: 'unknown', controlled_location:false }])
|
||||
logger.error("unknown choice: " + data.result.choice)
|
||||
alert("unknown choice: " + data.result.choice)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
deferred.resolveWith(canPlayWithOthers)
|
||||
}
|
||||
|
||||
|
||||
return deferred;
|
||||
}
|
||||
|
||||
gearUtils.guardAgainstActiveProfileMissing = function (app, backendInfo) {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// see audioWidgets.css
|
||||
.recording-controls {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ class ApiJamTracksController < ApiController
|
|||
|
||||
respond_to :json
|
||||
|
||||
def log
|
||||
@log || Logging.logger[ApiJamTracksController]
|
||||
end
|
||||
|
||||
def show
|
||||
@jam_track = JamTrack.find_by_plan_code!(params[:plan_code])
|
||||
end
|
||||
|
|
@ -70,7 +74,7 @@ class ApiJamTracksController < ApiController
|
|||
def download
|
||||
if @jam_track_right.valid?
|
||||
sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i
|
||||
if (@jam_track_right && @jam_track_right.ready?(sample_rate))
|
||||
if @jam_track_right && @jam_track_right.ready?(sample_rate)
|
||||
@jam_track_right.update_download_count
|
||||
@jam_track_right.last_downloaded_at = Time.now
|
||||
@jam_track_right.save!
|
||||
|
|
@ -86,7 +90,8 @@ class ApiJamTracksController < ApiController
|
|||
|
||||
def enqueue
|
||||
sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i
|
||||
@jam_track_right.enqueue_if_needed(sample_rate)
|
||||
enqueued = @jam_track_right.enqueue_if_needed(sample_rate)
|
||||
log.debug("jamtrack #{enqueued ? "ENQUEUED" : "NOT ENQUEUED"}: jam_track_right=#{@jam_track_right.id} sample_rate=#{sample_rate} ")
|
||||
render :json => { :message => "enqueued" }, :status => 200
|
||||
end
|
||||
|
||||
|
|
@ -102,14 +107,31 @@ class ApiJamTracksController < ApiController
|
|||
return
|
||||
end
|
||||
|
||||
jamtrack_ids = jamtrack_holder[:tracks]
|
||||
jamtracks = jamtrack_holder[:tracks]
|
||||
|
||||
unless jamtrack_ids.kind_of?(Array)
|
||||
unless jamtracks.kind_of?(Array)
|
||||
render :json => {message: 'jamtracks:tracks parameter must be an array'}, :status => 422
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
# jamtracks come in the form id-44 or id-48, so we need to do a little extra parsing
|
||||
puts "#{jamtracks.inspect}"
|
||||
jamtrack_ids = Set.new
|
||||
jamtracks_fq_ids = Set.new
|
||||
jamtracks.each do |jamtrack|
|
||||
rindex = jamtrack.rindex('-')
|
||||
if rindex
|
||||
id = jamtrack[0..(rindex-1)]
|
||||
jamtrack_ids << id
|
||||
jamtracks_fq_ids << jamtrack # includes sample rate
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
puts "#{jamtrack_ids.inspect} #{jamtracks_fq_ids.inspect}"
|
||||
@jam_tracks = JamTrackRight.list_keys(current_user, jamtrack_ids)
|
||||
@jamtracks_fq_ids = jamtracks_fq_ids
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1,9 +1,23 @@
|
|||
object @jam_tracks
|
||||
|
||||
node do |jam_track|
|
||||
{
|
||||
id: jam_track['id'].to_s,
|
||||
private: jam_track['private_key'],
|
||||
error: jam_track['private_key'] ? nil : ( jam_track['jam_track_right_id'] ? 'no_key' : 'not_purchased' )
|
||||
}
|
||||
|
||||
id = jam_track['id']
|
||||
result = { id: id }
|
||||
|
||||
if @jamtracks_fq_ids.include?("#{id}-44")
|
||||
result['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
|
||||
|
||||
if @jamtracks_fq_ids.include?("#{id}-48")
|
||||
result['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
|
||||
|
||||
result
|
||||
end
|
||||
|
|
@ -332,6 +332,5 @@ if defined?(Bundler)
|
|||
config.alerts_api_enabled = true
|
||||
|
||||
config.gear_check_ignore_high_latency = false
|
||||
config.gear_check_reload_audio = true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,5 +14,4 @@ Gon.global.recurly_public_api_key = Rails.application.config.recurly_public_api_
|
|||
Gon.global.one_free_jamtrack_per_user = Rails.application.config.one_free_jamtrack_per_user
|
||||
Gon.global.video_available = Rails.application.config.video_available
|
||||
Gon.global.gear_check_ignore_high_latency = Rails.application.config.gear_check_ignore_high_latency
|
||||
Gon.global.gear_check_reload_audio = Rails.application.config.gear_check_reload_audio
|
||||
Gon.global.env = Rails.env
|
||||
|
|
|
|||
|
|
@ -143,30 +143,33 @@ describe ApiJamTracksController do
|
|||
end
|
||||
|
||||
it "download depends on rights" do
|
||||
get :download, :id=>@jam_track.id
|
||||
get :download, :id=>@jam_track.id, sample_rate: 48
|
||||
response.status.should == 403
|
||||
|
||||
right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track)
|
||||
get :download, :id=>@jam_track.id
|
||||
get :download, :id=>@jam_track.id, sample_rate: 48
|
||||
response.status.should == 202
|
||||
right.download_count.should eq(0)
|
||||
right.private_key.should be_nil
|
||||
right.private_key_44.should be_nil
|
||||
right.private_key_48.should be_nil
|
||||
|
||||
qname = "#{ResqueSpec.queue_name(JamRuby::JamTracksBuilder)}"
|
||||
#puts "ResqueSpec.peek(qname)#{ResqueSpec.peek(qname)}"
|
||||
JamTracksBuilder.should have_queued(right.id,nil).in(:jam_tracks_builder)
|
||||
JamTracksBuilder.should have_queued(right.id,48).in(:jam_tracks_builder)
|
||||
|
||||
expect(ResqueSpec.peek(qname).present?).to eq(true)
|
||||
ResqueSpec.perform_next(qname)
|
||||
|
||||
JamTracksBuilder.should_not have_queued(right.id,nil).in(:jam_tracks_builder)
|
||||
right.reload
|
||||
right.private_key.should_not be_nil
|
||||
right.private_key_44.should be_nil
|
||||
right.private_key_48.should_not be_nil
|
||||
right.download_count.should eq(0)
|
||||
|
||||
get :download, :id=>@jam_track.id
|
||||
get :download, :id=>@jam_track.id, sample_rate: 48
|
||||
response.status.should == 302
|
||||
response.location.should =~ /.*#{Regexp.escape(right.filename)}.*/
|
||||
puts response.location
|
||||
response.location.should =~ /.*#{Regexp.escape(right.filename(:url_48))}.*/
|
||||
right.reload
|
||||
right.download_count.should eq(1)
|
||||
|
||||
|
|
@ -182,7 +185,8 @@ describe ApiJamTracksController do
|
|||
get :download, :id=>@jam_track.id, :sample_rate=>44
|
||||
response.status.should == 202
|
||||
right.download_count.should eq(0)
|
||||
right.private_key.should be_nil
|
||||
right.private_key_44.should be_nil
|
||||
right.private_key_48.should be_nil
|
||||
|
||||
qname = "#{ResqueSpec.queue_name(JamRuby::JamTracksBuilder)}"
|
||||
#puts "ResqueSpec.peek(qname)#{ResqueSpec.peek(qname)}"
|
||||
|
|
@ -193,12 +197,13 @@ describe ApiJamTracksController do
|
|||
|
||||
JamTracksBuilder.should_not have_queued(right.id, 44).in(:jam_tracks_builder)
|
||||
right.reload
|
||||
right.private_key.should_not be_nil
|
||||
right.private_key_44.should_not be_nil
|
||||
right.private_key_48.should be_nil
|
||||
right.download_count.should eq(0)
|
||||
|
||||
get :download, :id=>@jam_track.id, :sample_rate=>44
|
||||
response.status.should == 302
|
||||
response.location.should =~ /.*#{Regexp.escape(right.filename)}.*/
|
||||
response.location.should =~ /.*#{Regexp.escape(right.filename(:url_44))}.*/
|
||||
right.reload
|
||||
right.download_count.should eq(1)
|
||||
|
||||
|
|
@ -216,53 +221,66 @@ describe ApiJamTracksController do
|
|||
end
|
||||
|
||||
it "track with no rights" do
|
||||
get :keys, jamtracks: { tracks: [@jam_track.id] }
|
||||
get :keys, jamtracks: { tracks: ["#{@jam_track.id}-44"] }
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length.should == 1
|
||||
json[0]['id'].should == @jam_track.id.to_s
|
||||
json[0]['private'].should be_nil
|
||||
json[0]['error'].should == 'not_purchased'
|
||||
json[0]['44'].should_not be_nil
|
||||
json[0]['44']['private'].should be_nil
|
||||
json[0]['44']['error'].should == 'not_purchased'
|
||||
json[0]['48'].should be_nil
|
||||
end
|
||||
|
||||
it "track with no key" do
|
||||
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, private_key: nil, jam_track: @jam_track)
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, private_key_44: nil, private_key_48:nil, jam_track: @jam_track)
|
||||
|
||||
get :keys, jamtracks: { tracks: [@jam_track.id] }
|
||||
get :keys, jamtracks: { tracks: ["#{@jam_track.id}-44", "#{@jam_track.id}-48"] }
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length.should == 1
|
||||
json[0]['id'].should == @jam_track.id.to_s
|
||||
json[0]['private'].should be_nil
|
||||
json[0]['error'].should == 'no_key'
|
||||
json[0]['44'].should_not be_nil
|
||||
json[0]['44']['private'].should be_nil
|
||||
json[0]['44']['error'].should == 'no_key'
|
||||
json[0]['48'].should_not be_nil
|
||||
json[0]['48']['private'].should be_nil
|
||||
json[0]['48']['error'].should == 'no_key'
|
||||
end
|
||||
|
||||
it "track with key" do
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, private_key: 'abc', jam_track: @jam_track)
|
||||
get :keys, jamtracks: { tracks: [@jam_track.id] }
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, private_key_44: 'abc', private_key_48:nil, jam_track: @jam_track)
|
||||
get :keys, jamtracks: { tracks: ["#{@jam_track.id}-44", "#{@jam_track.id}-48"] }
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length.should == 1
|
||||
json[0]['id'].should == @jam_track.id.to_s
|
||||
json[0]['private'].should eq('abc')
|
||||
json[0]['error'].should be_nil
|
||||
json[0]['44'].should_not be_nil
|
||||
json[0]['44']['private'].should eq('abc')
|
||||
json[0]['44']['error'].should be_nil
|
||||
json[0]['48'].should_not be_nil
|
||||
json[0]['48']['private'].should be_nil
|
||||
json[0]['48']['error'].should == 'no_key'
|
||||
end
|
||||
|
||||
it "non-owning user asking for a real track" do
|
||||
right = FactoryGirl.create(:jam_track_right, user: FactoryGirl.create(:user), private_key: 'abc', jam_track: @jam_track)
|
||||
get :keys, jamtracks: { tracks: [@jam_track.id] }
|
||||
right = FactoryGirl.create(:jam_track_right, user: FactoryGirl.create(:user), private_key_44: 'abc', private_key_48:nil, jam_track: @jam_track)
|
||||
get :keys, jamtracks: { tracks: ["#{@jam_track.id}-44", "#{@jam_track.id}-48"] }
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json[0]['id'].should == @jam_track.id.to_s
|
||||
json[0]['private'].should be_nil
|
||||
json[0]['error'].should == 'not_purchased'
|
||||
json[0]['44'].should_not be_nil
|
||||
json[0]['44']['private'].should be_nil
|
||||
json[0]['44']['error'].should eq('not_purchased')
|
||||
json[0]['48'].should_not be_nil
|
||||
json[0]['48']['private'].should be_nil
|
||||
json[0]['48']['error'].should eq('not_purchased')
|
||||
end
|
||||
end
|
||||
|
||||
describe "enqueue" do
|
||||
it "success" do
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, signed: false)
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, signed_44: false, signed_48:false)
|
||||
right.signing_queued_at.should be_nil
|
||||
post :enqueue, {:format=>'json', :id=>right.jam_track.id}
|
||||
response.should be_success
|
||||
|
|
|
|||
|
|
@ -135,11 +135,15 @@ describe "JamTrack Shopping", :js => true, :type => :feature, :capybara_feature
|
|||
find_jamtrack jt_us
|
||||
|
||||
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jt_us.id}\"]").trigger(:click)
|
||||
find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jt_ww.id}\"]").trigger(:click)
|
||||
find('.shopping-sub-total', text: "Subtotal:$ #{jt_us.price}")
|
||||
find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||
|
||||
find('.shopping-sub-total', text: "Subtotal: $ #{jt_us.price + jt_ww.price}")
|
||||
find_jamtrack jt_ww
|
||||
|
||||
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jt_ww.id}\"]").trigger(:click)
|
||||
find('.shopping-sub-total', text: "Subtotal:$ #{jt_us.price + jt_ww.price}")
|
||||
#find('a.button-orange', text: 'CONTINUE SHOPPING').trigger(:click)
|
||||
|
||||
end
|
||||
|
||||
it "can expand" do
|
||||
|
|
|
|||
Loading…
Reference in New Issue