From dbaeb8d9968d014b4478ddb2abcadd6356ecc24a Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 25 Feb 2015 10:43:21 -0600 Subject: [PATCH] merged --- db/manifest | 3 +- db/up/recorded_jam_track_tracks.sql | 15 +++++++++ ruby/lib/jam_ruby.rb | 1 + ruby/lib/jam_ruby/models/jam_track.rb | 2 ++ ruby/lib/jam_ruby/models/jam_track_track.rb | 2 ++ .../models/recorded_jam_track_track.rb | 21 +++++++++++++ ruby/lib/jam_ruby/models/recording.rb | 31 ++++++++++++++++++- ruby/lib/jam_ruby/models/user.rb | 4 +++ ruby/spec/factories.rb | 7 ++++- ruby/spec/jam_ruby/models/recording_spec.rb | 27 ++++++++++++++++ web/app/assets/javascripts/jam_rest.js | 21 ++++++++++--- web/app/assets/javascripts/recordingModel.js | 1 - web/app/assets/javascripts/session.js | 19 ++++++++++++ web/app/assets/javascripts/sessionModel.js | 6 ++++ .../controllers/api_recordings_controller.rb | 9 +++++- web/app/views/api_music_sessions/show.rabl | 2 +- web/config/routes.rb | 1 + 17 files changed, 161 insertions(+), 11 deletions(-) create mode 100644 db/up/recorded_jam_track_tracks.sql create mode 100644 ruby/lib/jam_ruby/models/recorded_jam_track_track.rb diff --git a/db/manifest b/db/manifest index 9bb10cf65..fbdb8d856 100755 --- a/db/manifest +++ b/db/manifest @@ -253,4 +253,5 @@ recorded_backing_tracks.sql recorded_backing_tracks_add_filename.sql user_syncs_include_backing_tracks.sql remove_bpm_from_jamtracks.sql -jam_track_version.sql \ No newline at end of file +jam_track_version.sql +recorded_jam_track_tracks.sql \ No newline at end of file diff --git a/db/up/recorded_jam_track_tracks.sql b/db/up/recorded_jam_track_tracks.sql new file mode 100644 index 000000000..504c5e6ad --- /dev/null +++ b/db/up/recorded_jam_track_tracks.sql @@ -0,0 +1,15 @@ +ALTER TABLE recordings ADD COLUMN jam_track_id BIGINT REFERENCES jam_tracks(id); +ALTER TABLE recordings ADD COLUMN jam_track_initiator_id VARCHAR(64) REFERENCES users(id); + +CREATE TABLE recorded_jam_track_tracks ( + id BIGINT PRIMARY KEY, + user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + jam_track_track_id VARCHAR(64) REFERENCES jam_track_tracks(id) NOT NULL, + recording_id VARCHAR(64) REFERENCES recordings(id) NOT NULL, + discard BOOLEAN, + timeline JSON, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE recorded_jam_track_tracks ALTER COLUMN id SET DEFAULT nextval('tracks_next_tracker_seq'); \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index b94d7d9a2..f878bac21 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -138,6 +138,7 @@ require "jam_ruby/models/recorded_backing_track_observer" require "jam_ruby/models/recorded_track" require "jam_ruby/models/recorded_track_observer" require "jam_ruby/models/recorded_video" +require "jam_ruby/models/recorded_jam_track_track" require "jam_ruby/models/quick_mix" require "jam_ruby/models/quick_mix_observer" require "jam_ruby/models/share_token" diff --git a/ruby/lib/jam_ruby/models/jam_track.rb b/ruby/lib/jam_ruby/models/jam_track.rb index 552b4238b..18f8e77a5 100644 --- a/ruby/lib/jam_ruby/models/jam_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track.rb @@ -51,6 +51,8 @@ module JamRuby has_many :playing_sessions, :class_name => "JamRuby::ActiveMusicSession" + has_many :recordings, :class_name => "JamRuby::Recording" + accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true diff --git a/ruby/lib/jam_ruby/models/jam_track_track.rb b/ruby/lib/jam_ruby/models/jam_track_track.rb index 978ed29ab..c8d7c523f 100644 --- a/ruby/lib/jam_ruby/models/jam_track_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track_track.rb @@ -21,6 +21,8 @@ module JamRuby belongs_to :instrument, class_name: "JamRuby::Instrument" belongs_to :jam_track, class_name: "JamRuby::JamTrack" + has_many :recorded_jam_track_tracks, :class_name => "JamRuby::RecordedJamTrackTrack", :foreign_key => :jam_track_track_id, :dependent => :destroy + # create storage directory that will house this jam_track, as well as def store_dir "#{jam_track.store_dir}/tracks" diff --git a/ruby/lib/jam_ruby/models/recorded_jam_track_track.rb b/ruby/lib/jam_ruby/models/recorded_jam_track_track.rb new file mode 100644 index 000000000..f77615beb --- /dev/null +++ b/ruby/lib/jam_ruby/models/recorded_jam_track_track.rb @@ -0,0 +1,21 @@ +module JamRuby + # BackingTrack analog to JamRuby::RecordedTrack + class RecordedJamTrackTrack < ActiveRecord::Base + + belongs_to :user, :class_name => "JamRuby::User", :inverse_of => :recorded_jam_track_tracks + belongs_to :recording, :class_name => "JamRuby::Recording", :inverse_of => :recorded_jam_track_tracks + belongs_to :jam_track_track, :class_name => "JamRuby::JamTrackTrack", :inverse_of => :recorded_jam_track_tracks + + validates :user, presence: true + validates :jam_track_track, presence:true + + def self.create_from_jam_track_track(jam_track_track, recording) + recorded_jam_track_track = self.new + recorded_jam_track_track.recording = recording + recorded_jam_track_track.jam_track_track = jam_track_track + recorded_jam_track_track.save + recorded_jam_track_track + end + + end +end diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index 69d690962..bee8a2f95 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -12,6 +12,7 @@ module JamRuby has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id, :dependent => :destroy has_many :recorded_videos, :class_name => "JamRuby::RecordedVideo", :foreign_key => :recording_id, :dependent => :destroy has_many :recorded_backing_tracks, :class_name => "JamRuby::RecordedBackingTrack", :foreign_key => :recording_id, :dependent => :destroy + has_many :recorded_jam_track_tracks, :class_name => "JamRuby::RecordedJamTrackTrack", :foreign_key => :recording_id, :dependent => :destroy has_many :comments, :class_name => "JamRuby::RecordingComment", :foreign_key => "recording_id", :dependent => :destroy has_many :likes, :class_name => "JamRuby::RecordingLiker", :foreign_key => "recording_id", :dependent => :destroy has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy @@ -20,6 +21,8 @@ module JamRuby belongs_to :owner, :class_name => "JamRuby::User", :inverse_of => :owned_recordings, :foreign_key => 'owner_id' belongs_to :band, :class_name => "JamRuby::Band", :inverse_of => :recordings belongs_to :music_session, :class_name => "JamRuby::ActiveMusicSession", :inverse_of => :recordings, foreign_key: :music_session_id + belongs_to :jam_track, :class_name => "JamRuby::JamTrack", :inverse_of => :recordings, :foreign_key => 'jam_track_id' + belongs_to :jam_track_initiator, :class_name => "JamRuby::User", :inverse_of => :recorded_jam_tracks, :foreign_key => 'jam_track_initiator_id' accepts_nested_attributes_for :recorded_tracks, :mixes, :claimed_recordings, allow_destroy: true @@ -223,6 +226,14 @@ module JamRuby recording.recorded_backing_tracks << RecordedBackingTrack.create_from_backing_track(backing_track, recording) end end + + if music_session.jam_track + music_session.jam_track.jam_track_tracks.each do |jam_track_track| + recording.recorded_jam_tracks << RecordedJamTrack.create_from_jam_track_track(jam_track_track, recording) + end + recording.jam_track = music_session.jam_track + recording.jam_track_initiator = music_session.jam_track_initiator + end end end @@ -556,7 +567,7 @@ module JamRuby :recording_id => recorded_item.recording_id, :client_track_id => recorded_item.client_track_id, :next => recorded_item.id - }) + }) else end @@ -678,6 +689,24 @@ module JamRuby self.save(:validate => false) end + def add_timeline(timeline) + tracks = timeline["tracks"] + + raise JamArgumentError, "tracks must be specified" unless tracks + + jam_tracks = tracks.select {|track| track["type"] == "jam_track"} + jam_tracks.each do |client_jam_track| + recorded_jam_track_track = RecordedJamTrackTrack.find_by_jam_track_track_id(client_jam_track["id"]) + if recorded_jam_track_track + recorded_jam_track_track.timeline = client_jam_track["timeline"].to_json + recorded_jam_track_track.save! + else + @@log.error("unable to find JamTrackTrack with id #{recorded_jam_track_track.id}") + end + end + end + + private def self.validate_user_is_band_member(user, band) unless band.users.exists? user diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 3bb4c270a..a469ab69a 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -124,6 +124,10 @@ module JamRuby has_many :recorded_videos, :foreign_key => "user_id", :class_name => "JamRuby::RecordedVideo", :inverse_of => :user has_many :recorded_backing_tracks, :foreign_key => "user_id", :class_name => "JamRuby::RecordedBackingTrack", :inverse_of => :user has_many :quick_mixes, :foreign_key => "user_id", :class_name => "JamRuby::QuickMix", :inverse_of => :user + has_many :recorded_jam_track_tracks, :foreign_key => "user_id", :class_name => "JamRuby::RecordedJamTrackTrack", :inverse_of => :user + + # jam track recordings started + has_many :initiated_jam_track_recordings, :foreign_key => 'jam_track_initiator_id', :class_name => "JamRuby::Recording", :inverse_of => :jam_track_initiator # invited users has_many :invited_users, :foreign_key => "sender_id", :class_name => "JamRuby::InvitedUser" diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 42418a699..0da938fc1 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -268,7 +268,6 @@ FactoryGirl.define do association :recording, factory: :recording end - factory :recorded_video, :class => JamRuby::RecordedVideo do sequence(:client_video_source_id) { |n| "client_video_source_id-#{n}"} fully_uploaded true @@ -277,6 +276,12 @@ FactoryGirl.define do association :recording, factory: :recording end + factory :recorded_jam_track_track, :class => JamRuby::RecordedJamTrackTrack do + association :user, factory: :user + association :recording, factory: :recording + association :jam_track_track, factory: :jam_track_track + end + factory :instrument, :class => JamRuby::Instrument do description { |n| "Instrument #{n}" } end diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb index d2fd7c3b0..3d8515f29 100644 --- a/ruby/spec/jam_ruby/models/recording_spec.rb +++ b/ruby/spec/jam_ruby/models/recording_spec.rb @@ -1073,6 +1073,33 @@ describe Recording do RecordedVideo.find_by_id(video.id).should_not be_nil end end + + describe "add_timeline" do + + let!(:recorded_jam_track_track) {FactoryGirl.create(:recorded_jam_track_track)} + let(:recording) {recorded_jam_track_track.recording} + let(:timeline_data) {{"sample" => "data"}} + let(:good_timeline) { { + "tracks" => [ + { + "id" => recorded_jam_track_track.jam_track_track.id, + "timeline" => timeline_data, + "type" => "jam_track" + } + ] + } + } + + it "applies timeline data correctly" do + recording.add_timeline good_timeline + recorded_jam_track_track.reload + JSON.parse(recorded_jam_track_track.timeline).should eq(timeline_data) + end + + it "fails if no tracks data" do + expect { recording.add_timeline({}) }.to raise_error(JamRuby::JamArgumentError) + end + end end diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index df18a8070..dca216937 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -1585,13 +1585,23 @@ }); } - function validateUrlSite(url, sitetype) { + function validateUrlSite(url, sitetype) { + return $.ajax({ + type: "GET", + url: '/api/data_validation?sitetype='+sitetype+'&data=' + encodeURIComponent(url), + contentType: 'application/json' + }); + } + + function addRecordingTimeline(recordingId, data) { return $.ajax({ - type: "GET", - url: '/api/data_validation?sitetype='+sitetype+'&data=' + encodeURIComponent(url), - contentType: 'application/json' + type: "POST", + url: '/api/recordings/' + recordingId + '/timeline', + dataType: "json", + contentType: 'application/json', + data: JSON.stringify(data), }); - } + } function initialize() { return self; @@ -1734,6 +1744,7 @@ this.createSourceChange = createSourceChange; this.validateUrlSite = validateUrlSite; this.markRecordedBackingTrackSilent = markRecordedBackingTrackSilent; + this.addRecordingTimeline = addRecordingTimeline; return this; }; diff --git a/web/app/assets/javascripts/recordingModel.js b/web/app/assets/javascripts/recordingModel.js index 078a41c4d..a0e275f48 100644 --- a/web/app/assets/javascripts/recordingModel.js +++ b/web/app/assets/javascripts/recordingModel.js @@ -132,7 +132,6 @@ $self.triggerHandler('stoppedRecording', {'recordingId': recording.id, 'reason' : 'rest', 'details' : arguments}); } }); - }); return true; } diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index 937c83bdb..0bcb6d5f6 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -300,6 +300,21 @@ displayStoppingRecording(data); }) .on('stoppedRecording', function(e, data) { + + 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; @@ -1056,6 +1071,7 @@ // Default trackData to participant + no Mixer state. var trackData = { + type: 'backing_track', trackId: backingTrack.id, clientId: backingTrack.client_id, name: 'Backing', @@ -1140,6 +1156,7 @@ // Default trackData to participant + no Mixer state. var trackData = { + type: 'jam_track', trackId: oneOfTheTracks.id, clientId: oneOfTheTracks.client_id, name: name, @@ -1241,6 +1258,7 @@ // Default trackData to participant + no Mixer state. var trackData = { + type: 'metronome', trackId: "MS" + oneOfTheTracks.id, clientId: oneOfTheTracks.client_id, name: "Metronome", @@ -1340,6 +1358,7 @@ // Default trackData to participant + no Mixer state. var trackData = { + type: 'recorded_track', trackId: oneOfTheTracks.id, clientId: oneOfTheTracks.client_id, name: name, diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index 7487dec2d..b9fd3ea35 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -113,6 +113,11 @@ } } + // did I open up the current JamTrack? + function selfOpenedJamTracks() { + return currentSession && (currentSession.jam_track_initiator_id == context.JK.currentUserId) + } + function backingTrack() { if(currentSession) { // TODO: objectize this for VRFS-2665, VRFS-2666, VRFS-2667, VRFS-2668 @@ -830,6 +835,7 @@ this.isMasterMixMode = isMasterMixMode; this.isPersonalMixMode = isPersonalMixMode; this.getMixMode = getMixMode; + this.selfOpenedJamTracks = selfOpenedJamTracks; // ALERT HANDLERS this.onBackendMixerChanged = onBackendMixerChanged; diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb index 5caa975a8..89923b89d 100644 --- a/web/app/controllers/api_recordings_controller.rb +++ b/web/app/controllers/api_recordings_controller.rb @@ -1,7 +1,7 @@ class ApiRecordingsController < ApiController before_filter :api_signed_in_user, :except => [ :add_like ] - before_filter :lookup_recording, :only => [ :show, :stop, :claim, :discard, :keep, :delete_claim ] + before_filter :lookup_recording, :only => [ :show, :stop, :claim, :discard, :keep, :delete_claim, :add_timeline_data ] before_filter :lookup_recorded_track, :only => [ :download, :upload_next_part, :upload_sign, :upload_part_complete, :upload_complete ] before_filter :lookup_recorded_backing_track, :only => [ :backing_track_download, :backing_track_upload_next_part, :backing_track_upload_sign, :backing_track_upload_part_complete, :backing_track_upload_complete ] before_filter :lookup_recorded_video, :only => [ :video_upload_sign, :video_upload_start, :video_upload_complete ] @@ -377,6 +377,13 @@ class ApiRecordingsController < ApiController end end + # metadata + def add_timeline + @recording.add_timeline(params[:metadata]) + + render :json => {}, :status => 200 + end + private def lookup_recording diff --git a/web/app/views/api_music_sessions/show.rabl b/web/app/views/api_music_sessions/show.rabl index cd277c3fe..7c1b0c8de 100644 --- a/web/app/views/api_music_sessions/show.rabl +++ b/web/app/views/api_music_sessions/show.rabl @@ -13,7 +13,7 @@ if !current_user } else - attributes :id, :name, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id, :track_changes_counter, :max_score, :backing_track_path, :metronome_active + attributes :id, :name, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id, :track_changes_counter, :max_score, :backing_track_path, :metronome_active, :jam_track_initiator_id node :can_join do |session| session.can_join?(current_user, true) diff --git a/web/config/routes.rb b/web/config/routes.rb index 1613bf522..00fd25f38 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -451,6 +451,7 @@ SampleApp::Application.routes.draw do match '/recordings/:id/comments' => 'api_recordings#add_comment', :via => :post, :as => 'api_recordings_add_comment' match '/recordings/:id/likes' => 'api_recordings#add_like', :via => :post, :as => 'api_recordings_add_like' match '/recordings/:id/discard' => 'api_recordings#discard', :via => :post, :as => 'api_recordings_discard' + match '/recordings/:id/timeline' => 'api_recordings#add_timeline', :via => :post, :as => 'api_recordings_timeline' # Recordings - recorded_tracks match '/recordings/:id/tracks/:track_id' => 'api_recordings#show_recorded_track', :via => :get, :as => 'api_recordings_show_recorded_track'