diff --git a/admin/app/views/admin/jam_tracks/_jam_track_track_fields.html.slim b/admin/app/views/admin/jam_tracks/_jam_track_track_fields.html.slim index 14de2978c..70b003da3 100644 --- a/admin/app/views/admin/jam_tracks/_jam_track_track_fields.html.slim +++ b/admin/app/views/admin/jam_tracks/_jam_track_track_fields.html.slim @@ -12,10 +12,16 @@ i | before you can upload, you must select 'Update JamTrack' - else - = f.input :url, :as => :file, :label => 'Track file' + = f.input :url_48, :as => :file, :label => 'Track file (48kHz)' - unless f.object.nil? || f.object[:url].nil? .current_file_holder style='margin-bottom:10px' a href=f.object.sign_url(3600) style='padding:0 0 0 20px' | Download + = f.input :url_44, :as => :file, :label => 'Track file (44kHz)' + - unless f.object.nil? || f.object[:url].nil? + .current_file_holder style='margin-bottom:10px' + a href=f.object.sign_url(3600, 44) style='padding:0 0 0 20px' + | Download + = link_to_remove_association "Delete Track", f, class: 'button', style: 'margin-left:10px' \ No newline at end of file diff --git a/db/manifest b/db/manifest index ab12b759f..f89c4bbe2 100755 --- a/db/manifest +++ b/db/manifest @@ -261,4 +261,5 @@ widen_user_authorization_token.sql jam_track_version.sql recorded_jam_track_tracks.sql jam_track_jmep_data.sql +add_jam_track_bitrates.sql musician_search.sql diff --git a/db/up/add_jam_track_bitrates.sql b/db/up/add_jam_track_bitrates.sql new file mode 100644 index 000000000..aadfd2ead --- /dev/null +++ b/db/up/add_jam_track_bitrates.sql @@ -0,0 +1,14 @@ +ALTER TABLE jam_track_tracks RENAME COLUMN url TO url_48; +ALTER TABLE jam_track_tracks RENAME COLUMN md5 TO md5_48; +ALTER TABLE jam_track_tracks RENAME COLUMN length TO length_48; +ALTER TABLE jam_track_tracks ADD COLUMN url_44 VARCHAR; +ALTER TABLE jam_track_tracks ADD COLUMN md5_44 VARCHAR; +ALTER TABLE jam_track_tracks ADD COLUMN length_44 BIGINT; + +ALTER TABLE jam_track_rights RENAME COLUMN url TO url_48; +ALTER TABLE jam_track_rights RENAME COLUMN md5 TO md5_48; +ALTER TABLE jam_track_rights RENAME COLUMN length TO length_48; +ALTER TABLE jam_track_rights ADD COLUMN url_44 VARCHAR; +ALTER TABLE jam_track_rights ADD COLUMN md5_44 VARCHAR; +ALTER TABLE jam_track_rights ADD COLUMN length_44 BIGINT; + diff --git a/ruby/lib/jam_ruby/app/uploaders/jam_track_track_uploader.rb b/ruby/lib/jam_ruby/app/uploaders/jam_track_track_uploader.rb index 9defe1099..d2a80ce3d 100644 --- a/ruby/lib/jam_ruby/app/uploaders/jam_track_track_uploader.rb +++ b/ruby/lib/jam_ruby/app/uploaders/jam_track_track_uploader.rb @@ -23,6 +23,12 @@ class JamTrackTrackUploader < CarrierWave::Uploader::Base end def filename - "#{model.store_dir}/#{model.filename}" if model.id + if model.id + if mounted_as==:url_48 + "#{model.store_dir}/#{model.filename}" + else + "#{model.store_dir}/#{mounted_as}/#{model.filename}" + end + end end end diff --git a/ruby/lib/jam_ruby/jam_tracks_manager.rb b/ruby/lib/jam_ruby/jam_tracks_manager.rb index 37003d115..fc5dd5df3 100644 --- a/ruby/lib/jam_ruby/jam_tracks_manager.rb +++ b/ruby/lib/jam_ruby/jam_tracks_manager.rb @@ -12,13 +12,13 @@ module JamRuby @@log = Logging.logger[JamTracksManager] class << self - def save_jam_track_jkz(user, jam_track) + def save_jam_track_jkz(user, jam_track, bitrate=48) jam_track_right = jam_track.right_for_user(user) raise ArgumentError if jam_track_right.nil? - save_jam_track_right_jkz(jam_track_right) + save_jam_track_right_jkz(jam_track_right, bitrate) end - def save_jam_track_right_jkz(jam_track_right) + def save_jam_track_right_jkz(jam_track_right, bitrate=48) jam_track = jam_track_right.jam_track py_root = APP_CONFIG.jamtracks_dir Dir.mktmpdir do |tmp_dir| @@ -30,7 +30,7 @@ module JamRuby # use the jam_track_track ID as the filename.ogg/.wav, because it's important metadata nm = jam_track_track.id + File.extname(jam_track_track.filename) track_filename = File.join(tmp_dir, nm) - track_url = jam_track_track.sign_url + track_url = jam_track_track.sign_url(120, bitrate) copy_url_to_file(track_url, track_filename) copy_url_to_file(track_url, File.join(".", nm)) jam_file_opts << " -i '#{track_filename}+#{jam_track_track.part}'" @@ -54,11 +54,14 @@ module JamRuby #puts "stdout: #{out}, stderr: #{err}" 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")) - jam_track_right[:url] - + #raise ArgumentError, "output_jkz is empty #{output_jkz}" unless File.exists?(output_jkz) - - jam_track_right.url.store!(File.open(output_jkz, "rb")) + if bitrate==48 + jam_track_right.url_48.store!(File.open(output_jkz, "rb")) + 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") @@ -76,7 +79,7 @@ module JamRuby http.request request do |response| response_code = response.code.to_i unless response_code >= 200 && response_code <= 299 - puts "Response from server was #{response_code} / #{response.message}" + @@log.info "Response from server was #{response_code} / #{response.message}" raise "bad status code: #{response_code}. body: #{response.body}" end response.read_body do |chunk| diff --git a/ruby/lib/jam_ruby/models/jam_track.rb b/ruby/lib/jam_ruby/models/jam_track.rb index 4aa67bb1a..587160a46 100644 --- a/ruby/lib/jam_ruby/models/jam_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track.rb @@ -117,7 +117,7 @@ module JamRuby jam_track_rights.where("user_id=?", user).first end - def self.list_downloads(user, limit = 100, since = 0) + def self.list_downloads(user, limit = 100, since = 0, bitrate = 48) since = 0 unless since || since == '' # guard against nil downloads = [] @@ -125,16 +125,23 @@ module JamRuby .limit(limit) .where('jam_track_rights.id > ?', since) .each do |jam_track_right| - downloads << { + download = { :type => "jam_track", :id => jam_track_right.id.to_s, :jam_track_id => jam_track_right.jam_track_id, - :length => jam_track_right.length, - :md5 => jam_track_right.md5, - :url => jam_track_right.url, :created_at => jam_track_right.created_at, :next => jam_track_right.id } + if(bitrate==48) + download[:length] = jam_track_right.length_48 + download[:md5] = jam_track_right.md5_48 + download[:url] = jam_track_right.url_48 + else + download[:length] = jam_track_right.length_44 + download[:md5] = jam_track_right.md5_44 + download[:url] = jam_track_right.url_44 + end + downloads << download end next_id = downloads[-1][:next] if downloads.length > 0 diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index 3e82185ed..f7f1f7ddf 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -3,7 +3,9 @@ module JamRuby # describes what users have rights to which tracks class JamTrackRight < ActiveRecord::Base include JamRuby::S3ManagerMixin - attr_accessible :user, :jam_track, :user_id, :jam_track_id, :url, :md5, :length, :download_count + attr_accessible :user, :jam_track, :user_id, :jam_track_id, :download_count + attr_accessible :user_id, :jam_track_id, as: :admin + attr_accessible :url_48, :md5_48, :length_48, :url_44, :md5_44, :length_44 belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track belongs_to :jam_track, class_name: "JamRuby::JamTrack" @@ -15,7 +17,8 @@ module JamRuby validates_uniqueness_of :user_id, scope: :jam_track_id # Uploads the JKZ: - mount_uploader :url, JamTrackRightUploader + mount_uploader :url_48, JamTrackRightUploader + mount_uploader :url_44, JamTrackRightUploader before_destroy :delete_s3_files MAX_JAM_TRACK_DOWNLOADS = 1000 @@ -59,12 +62,17 @@ module JamRuby else raise "Error sending notification #{self.errors}" end - end - def finish_sign(length, md5) + + def finish_sign(length, md5, bitrate) self.last_signed_at = Time.now - self.length = length - self.md5 = md5 + if bitrate==48 + self.length_48 = length + self.md5_48 = md5 + else + self.length_44 = length + self.md5_44 = md5 + end self.signed = true self.error_count = 0 self.error_reason = nil @@ -81,36 +89,48 @@ module JamRuby # the idea is that this is used when a user who has the rights to this tries to download this JamTrack # we would verify their rights (can_download?), and generates a URL in response to the click so that they can download # but the url is short lived enough so that it wouldn't be easily shared - def sign_url(expiration_time = 120) - s3_manager.sign_url(self[:url], {:expires => expiration_time, :secure => false}) + def sign_url(expiration_time = 120, bitrate=48) + field_name = (bitrate==48) ? "url_48" : "url_44" + s3_manager.sign_url(self[field_name], {:expires => expiration_time, :secure => false}) end def delete_s3_files - remove_url! + remove_url_48! + remove_url_44! end - def enqueue + def enqueue(bitrate=48) begin JamTrackRight.where(:id => self.id).update_all(:signing_queued_at => Time.now, :signing_started_at => nil, :last_signed_at => nil) - Resque.enqueue(JamTracksBuilder, self.id) + Resque.enqueue(JamTracksBuilder, self.id, bitrate) true rescue Exception => e + puts "e: #{e}" # implies redis is down. we don't update started_at by bailing out here false end end # 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 + def enqueue_if_needed(bitrate=48) state = signing_state - if state == 'SIGNED' || state == 'SIGNING' || state == 'QUEUED' false else - enqueue + enqueue(bitrate) true end end + + # @return true if signed && file exists for the bitrate specifed: + def ready?(bitrate=48) + if bitrate==48 + self.signed && self.url_48.present? && self.url_48.file.exists? + else + self.signed && self.url_44.present? && self.url_44.file.exists? + end + end + # returns easy to digest state field # SIGNED - the package is ready to be downloaded # ERROR - the package was built unsuccessfully diff --git a/ruby/lib/jam_ruby/models/jam_track_track.rb b/ruby/lib/jam_ruby/models/jam_track_track.rb index 2e23aad3d..8fa2f9182 100644 --- a/ruby/lib/jam_ruby/models/jam_track_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track_track.rb @@ -7,9 +7,11 @@ module JamRuby # there should only be one Master per JamTrack, but there can be N Track per JamTrack TRACK_TYPE = %w{Track Master} - mount_uploader :url, JamTrackTrackUploader + mount_uploader :url_48, JamTrackTrackUploader + mount_uploader :url_44, JamTrackTrackUploader - attr_accessible :jam_track_id, :track_type, :instrument, :instrument_id, :position, :part, :url, as: :admin + attr_accessible :jam_track_id, :track_type, :instrument, :instrument_id, :position, :part, as: :admin + attr_accessible :url_44, :url_48, :md5_44, :md5_48, :length_44, :length_48, as: :admin validates :position, presence: true, numericality: {only_integer: true}, length: {in: 1..1000} validates :part, length: {maximum: 20} @@ -37,10 +39,11 @@ module JamRuby # the idea is that this is used when a user who has the rights to this tries to download this JamTrack # we would verify their rights (can_download?), and generates a URL in response to the click so that they can download # but the url is short lived enough so that it wouldn't be easily shared - def sign_url(expiration_time = 120) - s3_manager.sign_url(self[:url], {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false}) + def sign_url(expiration_time = 120, bitrate=48) + field_name = (bitrate==48) ? "url_48" : "url_44" + s3_manager.sign_url(self[field_name], {:expires => expiration_time, :response_content_type => 'audio/ogg', :secure => false}) end - + def can_download?(user) # I think we have to make a special case for 'previews', but maybe that's just up to the controller to not check can_download? jam_track.owners.include?(user) diff --git a/ruby/lib/jam_ruby/recurly_client.rb b/ruby/lib/jam_ruby/recurly_client.rb index 3bf68e991..c77e19121 100644 --- a/ruby/lib/jam_ruby/recurly_client.rb +++ b/ruby/lib/jam_ruby/recurly_client.rb @@ -86,7 +86,7 @@ module JamRuby begin jam_track = jam_track_right.jam_track account.subscriptions.find_each do |subscription| - puts "subscription.plan.plan_code: #{subscription.plan.plan_code} / #{jam_track.plan_code} / #{subscription.plan.plan_code == jam_track.plan_code}" + #puts "subscription.plan.plan_code: #{subscription.plan.plan_code} / #{jam_track.plan_code} / #{subscription.plan.plan_code == jam_track.plan_code}" if(subscription.plan.plan_code == jam_track.plan_code) subscription.terminate(:full) raise RecurlyClientError.new(subscription.errors) if subscription.errors.any? diff --git a/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb b/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb index 19d836462..395d12084 100644 --- a/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb +++ b/ruby/lib/jam_ruby/resque/jam_tracks_builder.rb @@ -7,25 +7,24 @@ require 'digest/md5' module JamRuby class JamTracksBuilder extend JamRuby::ResqueStats - + attr_accessor :jam_track_right_id, :bitrate @queue = :jam_tracks_builder def log @log || Logging.logger[JamTracksBuilder] end - attr_accessor :jam_track_right_id - - def self.perform(jam_track_right_id) + def self.perform(jam_track_right_id, bitrate=48) jam_track_builder = JamTracksBuilder.new() jam_track_builder.jam_track_right_id = jam_track_right_id + jam_track_builder.bitrate=bitrate jam_track_builder.run end def run + self.bitrate ||= 48 begin - log.info("jam_track_builder job starting. jam_track_right_id #{jam_track_right_id}") - + log.info("jam_track_builder job starting. jam_track_right_id #{jam_track_right_id}, bitrate: #{self.bitrate}") begin @jam_track_right = JamTrackRight.find(jam_track_right_id) @@ -37,16 +36,14 @@ module JamRuby # track that it's started ( and avoid db validations ) JamTrackRight.where(:id => @jam_track_right.id).update_all(:signing_started_at => Time.now, :should_retry => false) + JamRuby::JamTracksManager.save_jam_track_right_jkz(@jam_track_right, self.bitrate) - JamRuby::JamTracksManager.save_jam_track_right_jkz(@jam_track_right) - - length = @jam_track_right.url.size() + # If bitrate is 48 (the default), use that URL. Otherwise, use 44kHz: + length = (self.bitrate==48) ? @jam_track_right.url_48.size() : @jam_track_right.url_44.size() md5 = Digest::MD5.new + @jam_track_right.finish_sign(length, md5.to_s, self.bitrate) - @jam_track_right.finish_sign(length, md5.to_s) - - log.info "Signed jamtrack to #{@jam_track_right[:url]}" - + log.info "Signed #{self.bitrate}kHz jamtrack to #{@jam_track_right[:url]}" rescue Exception => e # record the error in the database post_error(e) diff --git a/ruby/spec/files/off.ogg b/ruby/spec/files/off.ogg new file mode 100644 index 000000000..743d6e3aa Binary files /dev/null and b/ruby/spec/files/off.ogg differ diff --git a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb index b92bfa04b..e06e212b2 100644 --- a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb +++ b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb @@ -67,26 +67,26 @@ describe JamTrackRight do jam_track_track = FactoryGirl.create(:jam_track_track) jam_track = jam_track_track.jam_track - uploader = JamTrackTrackUploader.new(jam_track_track, :url) + uploader = JamTrackTrackUploader.new(jam_track_track, :url_48) uploader.store!(File.open(ogg_path, 'rb')) jam_track_track.save! - jam_track_track[:url].should == jam_track_track.store_dir + '/' + jam_track_track.filename + jam_track_track[:url_48].should == jam_track_track.store_dir + '/' + jam_track_track.filename # verify it's on S3 s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) - s3.exists?(jam_track_track[:url]).should be_true - s3.length(jam_track_track[:url]).should == File.size?(ogg_path) + s3.exists?(jam_track_track[:url_48]).should be_true + s3.length(jam_track_track[:url_48]).should == File.size?(ogg_path) jam_track_right = JamTrackRight.create(:user=>user, :jam_track=>jam_track) #expect { JamRuby::JamTracksManager.save_jam_track_jkz(user, jam_track) #}.to_not raise_error(ArgumentError) jam_track_right.reload - jam_track_right[:url].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 # verify it's on S3 - url = jam_track_right[:url] + url = jam_track_right[:url_48] s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) s3.exists?(url).should be_true s3.length(url).should > File.size?(ogg_path) diff --git a/ruby/spec/jam_ruby/models/jam_track_track_spec.rb b/ruby/spec/jam_ruby/models/jam_track_track_spec.rb index 6cc5c3773..ed128a097 100644 --- a/ruby/spec/jam_ruby/models/jam_track_track_spec.rb +++ b/ruby/spec/jam_ruby/models/jam_track_track_spec.rb @@ -47,17 +47,17 @@ describe JamTrackTrack do it "uploads to s3 with correct name, and then downloads via signed URL" do jam_track_track = FactoryGirl.create(:jam_track_track) - uploader = JamTrackTrackUploader.new(jam_track_track, :url) + uploader = JamTrackTrackUploader.new(jam_track_track, :url_48) uploader.store!(File.open(TRACK_NAME)) # uploads file jam_track_track.save! # verify that the uploader stores the correct path - jam_track_track[:url].should == jam_track_track.store_dir + '/' + jam_track_track.filename + jam_track_track[:url_48].should == jam_track_track.store_dir + '/' + jam_track_track.filename # verify it's on S3 s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) - s3.exists?(jam_track_track[:url]).should be_true - s3.length(jam_track_track[:url]).should == 'abc'.length + s3.exists?(jam_track_track[:url_48]).should be_true + s3.length(jam_track_track[:url_48]).should == 'abc'.length # download it via signed URL, and check contents url = jam_track_track.sign_url diff --git a/ruby/spec/jam_ruby/resque/jam_tracks_builder_spec.rb b/ruby/spec/jam_ruby/resque/jam_tracks_builder_spec.rb new file mode 100644 index 000000000..bf72bd00d --- /dev/null +++ b/ruby/spec/jam_ruby/resque/jam_tracks_builder_spec.rb @@ -0,0 +1,83 @@ +require 'spec_helper' + +describe JamTracksBuilder do + include UsesTempFiles + include CarrierWave::Test::Matchers + + before (:all) do + @user = FactoryGirl.create(:user) + @jam_track = FactoryGirl.create(:jam_track) + original_storage = JamTrackTrackUploader.storage = :fog + original_storage = JamTrackRightUploader.storage = :fog + @s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) + end + + after(:all) do + JamTrackRightUploader.storage = @original_storage + JamTrackTrackUploader.storage = @original_storage + end + + before(:each) do + @s3.delete_folder('jam_tracks') + end + + it "should build" do + ogg_path = File.join('spec', 'files', 'on.ogg') + user = FactoryGirl.create(:user) + jam_track_track = FactoryGirl.create(:jam_track_track) + jam_track = jam_track_track.jam_track + + #uploader = JamTrackTrackUploader.new(jam_track_track, :url_48) + jam_track_track.url_48.store!(File.open(ogg_path, 'rb')) + jam_track_track.save! + + jam_track_track[:url_48].should == jam_track_track.store_dir + '/' + jam_track_track.filename + + # verify it's on S3 + @s3.exists?(jam_track_track[:url_48]).should be_true + @s3.length(jam_track_track[:url_48]).should == File.size?(ogg_path) + @s3.exists?(jam_track_track[:url_44]).should be_false + + # Check right + jam_track_right = JamTrackRight.create(:user=>user, :jam_track=>jam_track) + jam_track_right[:url_48].should be_nil + 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 + @s3.exists?(jam_track_track[:url_44]).should be_false + end + + describe "with bitrate 44" do + it "should build" do + ogg_path = File.join('spec', 'files', 'on.ogg') + user = FactoryGirl.create(:user) + + # Should build bitrate 44 and only bitrate 44: + jam_track_track = FactoryGirl.create(:jam_track_track) + jam_track = jam_track_track.jam_track + + # uploader = JamTrackTrackUploader.new(jam_track_track, :url_44) + # uploader.store!(File.open(ogg_path, 'rb')) + jam_track_track.url_44.store!(File.open(ogg_path, 'rb')) + jam_track_track.save! + + jam_track_track[:url_44].should == jam_track_track.store_dir + '/url_44/' + jam_track_track.filename + + # verify it's on S3 + @s3.exists?(jam_track_track[:url_44]).should be_true + @s3.length(jam_track_track[:url_44]).should == File.size?(ogg_path) + @s3.exists?(jam_track_track[:url_48]).should be_false + + # Check right + jam_track_right = JamTrackRight.create(:user=>user, :jam_track=>jam_track) + jam_track_right[:url_44].should be_nil + 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_not be_nil + @s3.exists?(jam_track_track[:url_48]).should be_false + end + end +end \ No newline at end of file diff --git a/ruby/spec/jam_ruby/resque/jam_tracks_cleaner_spec.rb b/ruby/spec/jam_ruby/resque/jam_tracks_cleaner_spec.rb index 36cb5a067..1c900bc52 100644 --- a/ruby/spec/jam_ruby/resque/jam_tracks_cleaner_spec.rb +++ b/ruby/spec/jam_ruby/resque/jam_tracks_cleaner_spec.rb @@ -26,20 +26,20 @@ describe JamTracksCleaner do jam_track_right.signed=true jam_track_right - jam_track_right.url.store!(File.open(RIGHT_NAME)) + 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].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 jam_track_right.reload # Should exist after uploading: - url = jam_track_right[:url] + url = jam_track_right[:url_48] s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) url.should_not be_nil s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) - s3.exists?(jam_track_right[:url]).should be_true + s3.exists?(jam_track_right[:url_48]).should be_true JamRuby::JamTracksCleaner.perform s3.exists?(url).should be_true diff --git a/web/app/assets/javascripts/jquery.listenbroadcast.js b/web/app/assets/javascripts/jquery.listenbroadcast.js index 73837da8f..00f87fcbe 100644 --- a/web/app/assets/javascripts/jquery.listenbroadcast.js +++ b/web/app/assets/javascripts/jquery.listenbroadcast.js @@ -92,32 +92,38 @@ .done(function(response) { if(!sessionInfo.mount) { - transition(PlayStateSessionOver); - destroy(); + if (sessionInfo.session_removed_at) { + transition(PlayStateSessionOver); + destroy(); + } } else { - recreateAudioElement(); + try { + recreateAudioElement(); - audioDomElement.load(); + audioDomElement.load(); - retryAttempts = 0; + retryAttempts = 0; - transition(PlayStateInitializing); + transition(PlayStateInitializing); - // keep this after transition, because any transition clears this timer - waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT); - logger.debug("setting buffering timeout"); - rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId); + // keep this after transition, because any transition clears this timer + waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT); + logger.debug("setting buffering timeout"); + rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId); - if(needsCanPlayGuard()) { - $audio.bind('canplay', function() { + if(needsCanPlayGuard()) { + $audio.bind('canplay', function() { + audioDomElement.play(); + }) + } + else { audioDomElement.play(); - }) + } } - else { - audioDomElement.play(); + catch (err) { + console.log("Catching error = %o", err); } - } }) } @@ -137,7 +143,12 @@ transition(PlayStateNone); - recreateAudioElement(); + try { + recreateAudioElement(); + } + catch (err) { + console.log("Catching error = %o", err); + } } function destroy() { @@ -145,7 +156,12 @@ //$audio.remove(); //$audio = null; //audioDomElement = null; - recreateAudioElement() + try { + recreateAudioElement(); + } + catch (err) { + console.log("Catching error = %o", err); + } // destroyed = true; //} } @@ -249,31 +265,37 @@ .done(function(response) { if(!sessionInfo.mount) { - transition(PlayStateSessionOver); - destroy(); + if (sessionInfo.session_removed_at) { + transition(PlayStateSessionOver); + destroy(); + } } else { // tell audio to stop/start, in attempt to retry //audioDomElement.pause(); - recreateAudioElement(); + try { + recreateAudioElement(); - audioDomElement.load(); - if(needsCanPlayGuard()) { - $audio.bind('canplay', function() { + audioDomElement.load(); + if(needsCanPlayGuard()) { + $audio.bind('canplay', function() { + audioDomElement.play(); + }) + } + else { audioDomElement.play(); - }) - } - else { - audioDomElement.play(); - } + } - transition(PlayStateRetrying); + transition(PlayStateRetrying); - waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT); + waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT); + } + catch (err) { + console.log("Catching error = %o", err); + } } - }) - + }); } } @@ -483,9 +505,11 @@ checkServer() .done(function(response) { if(!sessionInfo.mount) { - transition(PlayStateSessionOver); - destroy(); - }}) + if (sessionInfo.session_removed_at) { + transition(PlayStateSessionOver); + destroy(); + } + }}); } } @@ -694,10 +718,12 @@ else { mountInfo = null; - transition(PlayStateSessionOver); - destroy(); + if (sessionInfo.session_removed_at) { + transition(PlayStateSessionOver); + destroy(); + } - context.JK.app.layout.notify('This session can not currently broadcast') + context.JK.app.notify({"title": "Unable to Broadcast Session", "text": "This session cannot be broadcasted. The session organizer may have configured it to be private."}); } }) .fail(function() { diff --git a/web/app/controllers/api_jam_tracks_controller.rb b/web/app/controllers/api_jam_tracks_controller.rb index bd58c1f0f..e6838f629 100644 --- a/web/app/controllers/api_jam_tracks_controller.rb +++ b/web/app/controllers/api_jam_tracks_controller.rb @@ -25,7 +25,7 @@ class ApiJamTracksController < ApiController def downloads begin - render :json => JamTrack.list_downloads(current_user, params[:limit], params[:since]), :status => 200 + render :json => JamTrack.list_downloads(current_user, params[:limit], params[:since], params[:bitrate]), :status => 200 rescue render :json => { :message => "could not produce list of files" }, :status => 403 end @@ -33,13 +33,14 @@ class ApiJamTracksController < ApiController def download if @jam_track_right.valid? - if (@jam_track_right && @jam_track_right.signed && @jam_track_right.url.present? &&@jam_track_right.url.file.exists?) + bitrate = params[:bitrate] + if (@jam_track_right && @jam_track_right.ready?(bitrate)) @jam_track_right.update_download_count @jam_track_right.last_downloaded_at = Time.now @jam_track_right.save! - redirect_to @jam_track_right.sign_url + redirect_to @jam_track_right.sign_url(120, bitrate) else - @jam_track_right.enqueue_if_needed + @jam_track_right.enqueue_if_needed(bitrate) render :json => { :message => "not available, digitally signing Jam Track offline." }, :status => 202 end else @@ -48,8 +49,7 @@ class ApiJamTracksController < ApiController end def enqueue - @jam_track_right.enqueue_if_needed - + @jam_track_right.enqueue_if_needed(params[:bitrate]) render :json => { :message => "enqueued" }, :status => 200 end @@ -73,8 +73,6 @@ class ApiJamTracksController < ApiController end @jam_tracks = JamTrackRight.list_keys(current_user, jamtrack_ids) - - render "api_jam_tracks/list_keys", :layout => nil end private diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb index 89923b89d..b6f246e72 100644 --- a/web/app/controllers/api_recordings_controller.rb +++ b/web/app/controllers/api_recordings_controller.rb @@ -57,7 +57,7 @@ class ApiRecordingsController < ApiController @recorded_track.valid? if !@recorded_track.errors.any? @recorded_track.save! - redirect_to @recorded_track.sign_url + redirect_to @recorded_track.sign_url() else render :json => { :message => "download limit surpassed" }, :status => 404 end diff --git a/web/app/views/api_jam_tracks/list_keys.rabl b/web/app/views/api_jam_tracks/keys.rabl similarity index 100% rename from web/app/views/api_jam_tracks/list_keys.rabl rename to web/app/views/api_jam_tracks/keys.rabl diff --git a/web/jt_metadata.json b/web/jt_metadata.json new file mode 100644 index 000000000..19e02cdf6 --- /dev/null +++ b/web/jt_metadata.json @@ -0,0 +1 @@ +{"container_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150226-75079-44k4r2/jam-track-20.jkz", "coverart": null, "rsa_priv_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150226-75079-44k4r2/skey.pem", "tracks": [{"name": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150226-75079-44k4r2/19a1c759-94b8-4d36-92a7-00c9f3fba500.ogg", "trackName": "track_00"}], "rsa_pub_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150226-75079-44k4r2/pkey.pem", "jamktrack_info": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/tmpBKhxkz"} \ No newline at end of file diff --git a/web/spec/controllers/api_jam_tracks_controller_spec.rb b/web/spec/controllers/api_jam_tracks_controller_spec.rb index 831b111c5..210aa39f6 100644 --- a/web/spec/controllers/api_jam_tracks_controller_spec.rb +++ b/web/spec/controllers/api_jam_tracks_controller_spec.rb @@ -6,6 +6,7 @@ describe ApiJamTracksController do before(:all) do @original_storage = JamTrackTrackUploader.storage = :fog @original_storage_right = JamTrackRightUploader.storage = :fog + @s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) end after(:all) do @@ -76,7 +77,7 @@ describe ApiJamTracksController do it "finds a download" do #get "/download/#{right.id}/" right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) - get :download, { :format => 'json', :id => @jam_track.id } + get :download, { :format=>'json', :id=>@jam_track.id } response.should be_success response.status.should == 202 @@ -115,43 +116,81 @@ describe ApiJamTracksController do @jam_track = FactoryGirl.create(:jam_track) #jam_track_track.jam_track jam_track_track = @jam_track.jam_track_tracks.first - uploader = JamTrackTrackUploader.new(jam_track_track, :url) + # 48 kHz: + uploader = JamTrackTrackUploader.new(jam_track_track, :url_48) uploader.store!(File.open(@ogg_path, 'rb')) + + # 44 kHz: + uploader = JamTrackTrackUploader.new(jam_track_track, :url_44) + uploader.store!(File.open(File.join('spec', 'files', 'off.ogg'), 'rb')) + #jam_track_track.url.store!(File.open(ogg_path, "rb")) jam_track_track.save! jam_track_track.reload ResqueSpec.reset! end - it "download depends on rights" do - s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) - get :download, :id => @jam_track.id + it "download depends on rights" do + get :download, :id=>@jam_track.id 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 response.status.should == 202 right.download_count.should eq(0) right.private_key.should be_nil - JamTracksBuilder.should have_queued(right.id).in(:jam_tracks_builder) - qname = "#{ResqueSpec.queue_name(JamRuby::JamTracksBuilder)}" + #puts "ResqueSpec.peek(qname)#{ResqueSpec.peek(qname)}" + JamTracksBuilder.should have_queued(right.id,nil).in(:jam_tracks_builder) + expect(ResqueSpec.peek(qname).present?).to eq(true) ResqueSpec.perform_next(qname) - JamTracksBuilder.should_not have_queued(right.id).in(:jam_tracks_builder) + JamTracksBuilder.should_not have_queued(right.id,nil).in(:jam_tracks_builder) right.reload right.private_key.should_not be_nil right.download_count.should eq(0) - get :download, :id => @jam_track.id + get :download, :id=>@jam_track.id response.status.should == 302 response.location.should =~ /.*#{Regexp.escape(right.filename)}.*/ right.reload right.download_count.should eq(1) - notifications = Notification.where(:jam_track_right_id => right.id) + notifications = Notification.where(:jam_track_right_id=>right.id) + notifications.count.should == 1 + end + + it "supports multiple bitrates" do + get :download, :id=>@jam_track.id, :bitrate=>44 + response.status.should == 403 + + right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track) + get :download, :id=>@jam_track.id, :bitrate=>44 + response.status.should == 202 + right.download_count.should eq(0) + right.private_key.should be_nil + + qname = "#{ResqueSpec.queue_name(JamRuby::JamTracksBuilder)}" + #puts "ResqueSpec.peek(qname)#{ResqueSpec.peek(qname)}" + JamTracksBuilder.should have_queued(right.id,"44").in(:jam_tracks_builder) + + expect(ResqueSpec.peek(qname).present?).to eq(true) + ResqueSpec.perform_next(qname) + + JamTracksBuilder.should_not have_queued(right.id,"44").in(:jam_tracks_builder) + right.reload + right.private_key.should_not be_nil + right.download_count.should eq(0) + + get :download, :id=>@jam_track.id, :bitrate=>44 + response.status.should == 302 + response.location.should =~ /.*#{Regexp.escape(right.filename)}.*/ + right.reload + right.download_count.should eq(1) + + notifications = Notification.where(:jam_track_right_id=>right.id) notifications.count.should == 1 end end @@ -213,7 +252,7 @@ describe ApiJamTracksController do it "success" do right = FactoryGirl.create(:jam_track_right, user: @user, signed: false) right.signing_queued_at.should be_nil - post :enqueue, {:format => 'json', :id => right.jam_track.id} + post :enqueue, {:format=>'json', :id=>right.jam_track.id} response.should be_success right.reload @@ -225,7 +264,7 @@ describe ApiJamTracksController do it "success" do right = FactoryGirl.create(:jam_track_right, user: @user) - get :show_jam_track_right, {:id => right.jam_track.id} + get :show_jam_track_right, {:id=>right.jam_track.id} response.should be_success json = JSON.parse(response.body) json['signing_state'].should eq('QUIET') diff --git a/web/spec/files/off.ogg b/web/spec/files/off.ogg new file mode 100644 index 000000000..743d6e3aa Binary files /dev/null and b/web/spec/files/off.ogg differ