diff --git a/db/manifest b/db/manifest index 269651a25..33b6dec99 100755 --- a/db/manifest +++ b/db/manifest @@ -83,3 +83,4 @@ bands_geocoding.sql store_s3_filenames.sql discardable_recorded_tracks.sql music_sessions_have_claimed_recording.sql +discardable_recorded_tracks2.sql diff --git a/db/up/discardable_recorded_tracks2.sql b/db/up/discardable_recorded_tracks2.sql new file mode 100644 index 000000000..0d46581f9 --- /dev/null +++ b/db/up/discardable_recorded_tracks2.sql @@ -0,0 +1,2 @@ +ALTER TABLE recorded_tracks ALTER COLUMN discard DROP DEFAULT; +ALTER TABLE recorded_tracks ALTER COLUMN discard DROP NOT NULL; \ No newline at end of file diff --git a/ruby/lib/jam_ruby/constants/validation_messages.rb b/ruby/lib/jam_ruby/constants/validation_messages.rb index db0c7424a..c46d08ab3 100644 --- a/ruby/lib/jam_ruby/constants/validation_messages.rb +++ b/ruby/lib/jam_ruby/constants/validation_messages.rb @@ -49,6 +49,7 @@ module ValidationMessages ALREADY_PLAYBACK_RECORDING = "already playing a recording" NO_LONGER_RECORDING = "no longer recording" NOT_IN_SESSION = "not in session" + PREVIOUS_RECORDING_STILL_BEING_FINALIZED = "still has previous recording being finalized" # recorded tracks ALREADY_UPLOADED = "already set" diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 208ee3d95..e419d39ba 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -179,6 +179,10 @@ module JamRuby return self.users.exists? user end + def most_recent_recording + recordings.where(:music_session_id => self.id).order('created_at desc').limit(1).first + end + # is this music session currently recording? def is_recording? recordings.where(:duration => nil).count > 0 diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index c09059842..78c244f29 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -14,6 +14,7 @@ module JamRuby has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id validates :music_session, :presence => true validate :not_already_recording, :on => :create + validate :not_still_finalizing_previous, :on => :create validate :not_playback_recording, :on => :create validate :already_stopped_recording @@ -23,6 +24,28 @@ module JamRuby end end + def not_still_finalizing_previous + # after a recording is done, users need to keep or discard it. + # this checks if the previous recording is still being finalized + + unless music_session.is_recording? + previous_recording = music_session.most_recent_recording + if previous_recording + previous_recording.recorded_tracks.each do |recorded_track| + # if at least one user hasn't taken any action yet... + if recorded_track.discard.nil? + # and they are still around and in this music session still... + connection = Connection.find_by_client_id(recorded_track.client_id) + if !connection.nil? && connection.music_session == music_session + errors.add(:music_session, ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED) + break + end + end + end + end + end + end + def not_playback_recording if music_session.is_playing_recording? errors.add(:music_session, ValidationMessages::ALREADY_PLAYBACK_RECORDING) @@ -39,7 +62,7 @@ module JamRuby unless self.users.exists?(user) raise PermissionError, "user was not in this session" end - RecordedTrack.where(:recording_id=> self.id).where(:user_id=> user.id) + recorded_tracks.where(:user_id=> user.id) end def has_access?(user) @@ -91,12 +114,13 @@ module JamRuby self end + # Called when a user wants to "claim" a recording. To do this, the user must have been one of the tracks in the recording. def claim(user, name, description, genre, is_public, is_downloadable) unless self.users.exists?(user) raise PermissionError, "user was not in this session" - end + end claimed_recording = ClaimedRecording.new claimed_recording.user = user @@ -108,8 +132,17 @@ module JamRuby claimed_recording.is_downloadable = is_downloadable self.claimed_recordings << claimed_recording + if claimed_recording.save + discard(user) + end + claimed_recording end + + # the user votes to discard their tracks for this recording + def discard(user) + recorded_tracks_for_user(user).update_all(:discard => true) + end # Find out if all the tracks for this recording have been uploaded def uploaded? @@ -119,11 +152,6 @@ module JamRuby return true end - # Discards this recording and schedules deletion of all files associated with it. - def discard - self.destroy - end - def self.list_downloads(user, limit = 100, since = 0) since = 0 unless since || since == '' # guard against nil downloads = [] diff --git a/ruby/spec/jam_ruby/models/claimed_recording_spec.rb b/ruby/spec/jam_ruby/models/claimed_recording_spec.rb index dec39796a..bca0b4b0e 100644 --- a/ruby/spec/jam_ruby/models/claimed_recording_spec.rb +++ b/ruby/spec/jam_ruby/models/claimed_recording_spec.rb @@ -1,12 +1,15 @@ require 'spec_helper' def valid_claimed_recording - @claimed_recording.name = "hello" - @claimed_recording.description = "description" - @claimed_recording.genre = Genre.first - @claimed_recording.is_public = true - @claimed_recording.is_downloadable = true - @claimed_recording + @name = "hello" + @description = "description" + @genre = Genre.first + @is_public = true + @is_downloadable = true +end + +def make_claim + @claimed_recording = @recording.claim(@user, @name, @description, @genre, @is_public, @is_downloadable) end describe ClaimedRecording do @@ -22,33 +25,37 @@ describe ClaimedRecording do @recording = Recording.start(@music_session, @user) @recording.stop @recording.reload - @genre = FactoryGirl.create(:genre) - @recording.claim(@user, "name", "description", @genre, true, true) - @recording.reload - @claimed_recording = @recording.claimed_recordings.first + end describe "sucessful save" do it "with default case" do valid_claimed_recording - @claimed_recording.save.should be_true + make_claim + @claimed_recording.errors.any?.should be_false + @recording.reload + @recording.recorded_tracks.first.discard.should be_false end end describe "update name" do it "with nil" do valid_claimed_recording - @claimed_recording.name = nil - @claimed_recording.save.should be_false + @name = nil + make_claim + @claimed_recording.errors.any?.should be_true @claimed_recording.errors[:name].length.should == 2 @claimed_recording.errors[:name].select { |value| value.include?("can't be blank") }.length.should == 1 @claimed_recording.errors[:name].select { |value| value.include?("is too short") }.length.should == 1 + @recording.reload + @recording.recorded_tracks.first.discard.should be_nil end it "too short" do valid_claimed_recording - @claimed_recording.name = "a" - @claimed_recording.save.should be_false + @name = "a" + make_claim + @claimed_recording.errors.any?.should be_true @claimed_recording.errors[:name].length.should == 1 @claimed_recording.errors[:name].select { |value| value.include?("is too short") }.length.should == 1 end @@ -57,16 +64,18 @@ describe ClaimedRecording do describe "update description" do it "with nil" do valid_claimed_recording - @claimed_recording.description = nil - @claimed_recording.save.should be_true + @description = nil + make_claim + @claimed_recording.errors.any?.should be_false end end describe "update is_public" do it "with nil" do valid_claimed_recording - @claimed_recording.is_public = nil - @claimed_recording.save.should be_false + @is_public = nil + make_claim + @claimed_recording.errors.any?.should be_true @claimed_recording.errors[:is_public].length.should == 1 @claimed_recording.errors[:is_public].should == ["is not included in the list"] end @@ -75,8 +84,9 @@ describe ClaimedRecording do describe "update is_downloadable" do it "with nil" do valid_claimed_recording - @claimed_recording.is_downloadable = nil - @claimed_recording.save.should be_false + @is_downloadable = nil + make_claim + @claimed_recording.errors.any?.should be_true @claimed_recording.errors[:is_downloadable].length.should == 1 @claimed_recording.errors[:is_downloadable].should == ["is not included in the list"] end @@ -85,8 +95,9 @@ describe ClaimedRecording do describe "update genre" do it "with nil" do valid_claimed_recording - @claimed_recording.genre = nil - @claimed_recording.save.should be_false + @genre = nil + make_claim + @claimed_recording.errors.any?.should be_true @claimed_recording.errors[:genre].length.should == 1 @claimed_recording.errors[:genre].should == ["can't be blank"] end @@ -94,6 +105,8 @@ describe ClaimedRecording do describe "multiple claims" do it "not valid" do + valid_claimed_recording + make_claim duplicate = @recording.claim(@user, "name", "description", @genre, true, true) duplicate.valid?.should be_false duplicate.errors[:recording_id].should == ['has already been taken'] diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb index 7300d0637..7640cfc28 100644 --- a/ruby/spec/jam_ruby/models/recording_spec.rb +++ b/ruby/spec/jam_ruby/models/recording_spec.rb @@ -316,6 +316,44 @@ describe Recording do timeline.last["end"].should == true end + describe "chance for everyone to keep or discard" do + before(:each) do + @user2 = FactoryGirl.create(:user) + @connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session) + @track2 = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument) + + @recording = Recording.start(@music_session, @user) + @recording.stop + @recording.reload + end + + it "no one votes" do + @recording2 = Recording.start(@music_session, @user) + @recording2.errors.any?.should be_true + @recording2.errors[:music_session].should == [ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED] + end + + it "only one discards" do + @recording.discard(@user) + @recording2 = Recording.start(@music_session, @user) + @recording2.errors.any?.should be_true + @recording2.errors[:music_session].should == [ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED] + end + + it "everyone discards" do + @recording.discard(@user) + @recording.discard(@user2) + @recording2 = Recording.start(@music_session, @user) + @recording2.errors.any?.should be_false + end + + it "one discards, the other leaves the session" do + @recording.discard(@user) + @connection2.delete + @recording2 = Recording.start(@music_session, @user2) + @recording2.errors.any?.should be_false + end + end end diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js index b002ca51e..b79a32516 100644 --- a/web/app/assets/javascripts/fakeJamClient.js +++ b/web/app/assets/javascripts/fakeJamClient.js @@ -549,7 +549,7 @@ var possibleAnswers = ['HQ', 'RT', 'MISSING', 'PARTIALLY_MISSING']; - $.each(recordings.claimed_recordings, function(i, recordings) { + $.each(recordings, function(i, recording) { // just make up a random yes-hq/yes-rt/missing answer var recordingResult = {}; recordingResult['aggregate_state'] = possibleAnswers[Math.floor((Math.random()*4))]; diff --git a/web/app/assets/javascripts/localRecordingsDialog.js b/web/app/assets/javascripts/localRecordingsDialog.js index 53850b3b2..27e1bc3e8 100644 --- a/web/app/assets/javascripts/localRecordingsDialog.js +++ b/web/app/assets/javascripts/localRecordingsDialog.js @@ -48,10 +48,10 @@ emptyList(); - var recordings = []; var $tbody = tbody(); - var localResults = context.jamClient.GetLocalRecordingState({claimed_recordings: claimedRecordings}); + var recordings = $.map(claimedRecordings, function(val, i) { return val.recording; }); + var localResults = context.jamClient.GetLocalRecordingState({recordings: recordings}); if(localResults['error']) { app.notify({ @@ -113,7 +113,7 @@ rest.startPlayClaimedRecording({id: context.JK.CurrentSessionModel.id(), claimed_recording_id: claimedRecording.id}) .done(function(response) { var recordingId = $(this).attr('data-recording-id'); - var openRecordingResult = context.jamClient.OpenRecording(claimedRecording); + var openRecordingResult = context.jamClient.OpenRecording(claimedRecording.recording); logger.debug("OpenRecording response: %o", openRecordingResult); diff --git a/web/app/assets/javascripts/playbackControls.js b/web/app/assets/javascripts/playbackControls.js index 071497642..79282670d 100644 --- a/web/app/assets/javascripts/playbackControls.js +++ b/web/app/assets/javascripts/playbackControls.js @@ -5,15 +5,34 @@ "use strict"; + var PlaybackMode = { + NoPlayback: 0, + EveryWhere: 1, + PrivatePreview: 2, + PreviewToAll: 3, + LastPbMode: 4 + }; + + + context.JK = context.JK || {}; - context.JK.PlaybackControls = function($parentElement){ + context.JK.PlaybackControls = function($parentElement, options){ + + options = $.extend(false, {playmodeControlsVisible:false}, options); + var logger = context.JK.logger; + if($parentElement.length == 0) { + logger.debug("no $parentElement specified in PlaybackControls"); + } + var $playButton = $('.play-button img.playbutton', $parentElement); var $pauseButton = $('.play-button img.pausebutton', $parentElement); var $currentTime = $('.recording-current', $parentElement); var $duration = $('.duration-time', $parentElement); var $sliderBar = $('.recording-playback', $parentElement); var $slider = $('.recording-slider', $parentElement); + var $playmodeButton = $('.playback-mode-buttons.icheckbuttons input', $parentElement); + var $self = $(this); var playbackPlaying = false; @@ -26,13 +45,15 @@ var playingWhenDragStart = false; var draggingUpdateTimer = null; var canUpdateBackend = false; + var playbackMode = PlaybackMode.EveryWhere; + var monitorPlaybackTimeout = null; function startPlay() { updateIsPlaying(true); if(endReached) { update(0, playbackDurationMs, playbackPlaying); } - $self.triggerHandler('play'); + $self.triggerHandler('play', {playbackMode: playbackMode}); } function stopPlay() { @@ -94,7 +115,7 @@ updateOffsetBasedOnPosition(offset); updateSliderPosition(playbackPositionMs); return false; - }) + }); $slider.draggable({ axis: 'x', @@ -104,6 +125,34 @@ drag: onDrag }); + + if(options.playmodeControlsVisible) { + $('.playback-mode-buttons.icheckbuttons', $parentElement).show(); + } + + $playmodeButton.iCheck({ + checkboxClass: 'icheckbox_minimal', + radioClass: 'iradio_minimal', + inheritClass: true + }); + + + $playmodeButton.on('ifChecked', function(e) { + var playmode = $(this).val(); + console.log("set new playmode", playmode); + setPlaybackMode(playmode); + }); + + function monitorRecordingPlayback() { + var isPlaying = context.jamClient.isSessionTrackPlaying(); + var positionMs = context.jamClient.SessionCurrrentPlayPosMs(); + var durationMs = context.jamClient.SessionGetTracksPlayDurationMs(); + + update(positionMs, durationMs, isPlaying); + + monitorPlaybackTimeout = setTimeout(monitorRecordingPlayback, 500); + } + function update(currentTimeMs, durationTimeMs, isPlaying) { if(dragging) { @@ -111,6 +160,7 @@ } // at the end of the play, the duration sets to 0, as does currentTime. but isPlaying does not reset to + console.log("currentTimeMs, durationTimeMs", currentTimeMs, durationTimeMs); if(currentTimeMs == 0 && durationTimeMs == 0) { if(isPlaying) { isPlaying = false; @@ -175,9 +225,43 @@ } } + function setPlaybackMode(mode) { + if(mode == 'preview-to-all') { + playbackMode = PlaybackMode.PreviewToAll; + } + else if(mode == 'preview-to-me') { + playbackMode = PlaybackMode.PrivatePreview; + } + else if(mode == 'eveywhere') { + playbackMode = PlaybackMode.EveryWhere; + } + else { + logger.error("unable to set playback mode", mode); + } + + // let the mode change immediately affect the behavior of the stream + if(playbackPlaying) { + stopPlay(); + startPlay(); + } + } + + function startMonitor() { + monitorRecordingPlayback(); + } + + function stopMonitor() { + if(monitorPlaybackTimeout!= null) { + clearTimeout(monitorPlaybackTimeout); + monitorPlaybackTimeout = null; + } + } this.update = update; + this.setPlaybackMode = setPlaybackMode; + this.startMonitor = startMonitor; + this.stopMonitor = stopMonitor; return this; } diff --git a/web/app/assets/javascripts/recordingFinishedDialog.js b/web/app/assets/javascripts/recordingFinishedDialog.js index 80a8ee44a..e7200038b 100644 --- a/web/app/assets/javascripts/recordingFinishedDialog.js +++ b/web/app/assets/javascripts/recordingFinishedDialog.js @@ -6,14 +6,22 @@ var logger = context.JK.logger; var rest = context.JK.Rest(); var playbackControls = null; + var recording = null; // deferred object function resetForm() { + // remove all display errors $('#recording-finished-dialog form .error-text').remove() $('#recording-finished-dialog form .error').removeClass("error") } function beforeShow() { + if(recording == null) { + alert("recording data should not be null"); + app.layout.closeDialog('recordingFinished'); + return false; + } + resetForm(); var parentSelector = '#recording-finished-dialog div.genre-selector'; @@ -25,26 +33,73 @@ var genreDescription = currentOrLastSession.genres[0]; context.JK.GenreSelectorHelper.setSelectedGenres(parentSelector, [genreDescription]); } + + var localResults = context.jamClient.GetLocalRecordingState({recordings: [recording]}); + + + if(localResults['error']) { + app.notify({ + title : "Unable to Open Recording for Playback", + text : localResults['error'], + icon_url: "/assets/content/icon_alert_big.png" + }); + } + else { + var localResult = localResults.recordings[0]; + if(localResult.aggregate_state == 'MISSING') { + app.notify({ + title : "Unable to Open Recording for Playback", + text : "All tracks associated with the recording are missing", + icon_url: "/assets/content/icon_alert_big.png" + }); + } + else if(localResult.aggregate_state == 'PARTIALLY_MISSING') { + app.notify({ + title : "Unable to Open Recording for Playback", + text: "Some tracks associated with the recording are missing", + icon_url: "/assets/content/icon_alert_big.png" + }) + } + else { + + // load recording + var openRecordingResult = context.jamClient.OpenRecording(recording); + + logger.debug("OpenRecording response: %o", openRecordingResult); + + if(openRecordingResult.error) { + app.notify({ + "title": "Can't Open Recording", + "text": openRecordingResult.error, + "icon_url": "/assets/content/icon_alert_big.png" + }); + } + + playbackControls.startMonitor(); + } + } + } function afterHide() { - + recording = null; + playbackControls.stopMonitor(); + context.jamClient.CloseRecording(); } function discardRecording(e) { resetForm(); registerDiscardRecordingHandlers(false); - var recordingId = JK.CurrentSessionModel.recordingModel.currentOrLastRecordingId(); rest.discardRecording({ - id: recordingId + id: recording.id }) .done(function() { - console.error("recording discarded by user. recordingId=%o", recordingId); + console.error("recording discarded by user. recordingId=%o", recording.id); }) .fail(function(jqXHR){ - console.error("recording discard by user failed. recordingId=%o. reason: %o", recordingId, jqXHR.responseText); + console.error("recording discard by user failed. recordingId=%o. reason: %o", recording.id, jqXHR.responseText); }) .always(function() { app.layout.closeDialog('recordingFinished') @@ -56,7 +111,6 @@ resetForm(); registerClaimRecordingHandlers(false); - var recordingId = JK.CurrentSessionModel.recordingModel.currentOrLastRecordingId(); var name = $('#recording-finished-dialog form input[name=name]').val(); var description = $('#recording-finished-dialog form textarea[name=description]').val(); @@ -65,7 +119,7 @@ var is_downloadable = $('#recording-finished-dialog form input[name=is_downloadable]').is(':checked'); rest.claimRecording({ - id : recordingId, + id : recording.id, name: name, description: description, genre: genre, @@ -136,12 +190,12 @@ context.jamClient.SessionStopPlay(); } - function onPlay() { + function onPlay(e, data) { logger.debug("calling jamClient.SessionStartPlay"); - context.jamClient.SessionStartPlay(); + context.jamClient.SessionStartPlay(data.playbackMode); } - function onChangePlayPosition() { + function onChangePlayPosition(e, data) { logger.debug("calling jamClient.SessionTrackSeekMs(" + data.positionMs + ")"); context.jamClient.SessionTrackSeekMs(data.positionMs); } @@ -155,6 +209,15 @@ .on('change-position', onChangePlayPosition); } + function setRecording(recordingData) { + if(recording != null) { + //XXX - prevent start/stop recording mashing; protect this dialog + logger.error("unable to set recording data over existing recording data. this coudld be due to start/stop recording mashing"); + return; + } + recording = recordingData; + } + function initialize(){ var dialogBindings = { 'beforeShow' : beforeShow, @@ -170,6 +233,7 @@ this.initialize = initialize; + this.setRecording = setRecording; } return this; diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index cb26fcb39..49264de6f 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -13,6 +13,7 @@ var configureTrackDialog; var addNewGearDialog; var localRecordingsDialog = null; + var recordingFinishedDialog = null; var screenActive = false; var currentMixerRangeMin = null; var currentMixerRangeMax = null; @@ -25,7 +26,6 @@ var startingRecording = false; // double-click guard var claimedRecording = null; var playbackControls = null; - var monitorPlaybackTimeout = null; var rest = JK.Rest(); @@ -364,16 +364,6 @@ .fail(app.ajaxError); } - function monitorRecordingPlayback() { - var isPlaying = context.jamClient.isSessionTrackPlaying(); - var positionMs = context.jamClient.SessionCurrrentPlayPosMs(); - var durationMs = context.jamClient.SessionGetTracksPlayDurationMs(); - - playbackControls.update(positionMs, durationMs, isPlaying); - - monitorPlaybackTimeout = setTimeout(monitorRecordingPlayback, 500); - } - function handleTransitionsInRecordingPlayback() { // let's see if we detect a transition to start playback or stop playback @@ -382,10 +372,10 @@ if(claimedRecording == null && (currentSession && currentSession.claimed_recording != null)) { // this is a 'started with a claimed_recording' transition. // we need to start a timer to watch for the state of the play session - monitorRecordingPlayback(); + playbackControls.startMonitor(); } else if(claimedRecording && (currentSession == null || currentSession.claimed_recording == null)) { - clearTimeout(monitorPlaybackTimeout); + playbackControls.stopMonitor(); } claimedRecording = currentSession == null ? null : currentSession.claimed_recording; @@ -434,7 +424,7 @@ if ($('.session-recordings .track').length === 0) { $('.session-recordings .when-empty').show(); $('.session-recording-name-wrapper').hide(); - $('.recording-controls').hide(); + $('.session-recordings .recording-controls').hide(); } } @@ -917,14 +907,13 @@ var $destination = $(parentSelector); $('.session-recordings .when-empty').hide(); $('.session-recording-name-wrapper').show(); - $('.recording-controls').show(); + $('.session-recordings .recording-controls').show(); var template = $('#template-session-track').html(); var newTrack = $(context.JK.fillTemplate(template, trackData)); $destination.append(newTrack); if(trackData.preMasteredClass) { context.JK.helpBubble($('.track-instrument', newTrack), 'pre-processed-track', {}, {offsetParent: newTrack.closest('.content-body')}); - } // Render VU meters and gain fader @@ -1247,6 +1236,7 @@ function promptUserToSave(recordingId) { rest.getRecording( {id: recordingId} ) .done(function(recording) { + recordingFinishedDialog.setRecording(recording); app.layout.showDialog('recordingFinished'); }) .fail(app.ajaxError); @@ -1293,9 +1283,9 @@ context.jamClient.SessionStopPlay(); } - function onPlay() { + function onPlay(e, data) { logger.debug("calling jamClient.SessionStartPlay"); - context.jamClient.SessionStartPlay(); + context.jamClient.SessionStartPlay(data.playbackMode); } function onChangePlayPosition(e, data){ @@ -1312,7 +1302,6 @@ } } - function events() { $('#session-resync').on('click', sessionResync); $('#session-contents').on("click", '[action="delete"]', deleteSession); @@ -1330,13 +1319,13 @@ .on('change-position', onChangePlayPosition); } - this.initialize = function(localRecordingsDialogInstance) { + this.initialize = function(localRecordingsDialogInstance, recordingFinishedDialogInstance) { localRecordingsDialog = localRecordingsDialogInstance; + recordingFinishedDialog = recordingFinishedDialogInstance; context.jamClient.SetVURefreshRate(150); playbackControls = new context.JK.PlaybackControls($('.session-recordings .recording-controls')); events(); - var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow, diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index c610ea73e..f62a3dfad 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -38,7 +38,7 @@ function recordedTracks() { if(currentSession && currentSession.claimed_recording) { - return currentSession.claimed_recording.recorded_tracks + return currentSession.claimed_recording.recording.recorded_tracks } else { return null; diff --git a/web/app/assets/stylesheets/client/createSession.css.scss b/web/app/assets/stylesheets/client/createSession.css.scss index f345b2ac4..c9fe9d001 100644 --- a/web/app/assets/stylesheets/client/createSession.css.scss +++ b/web/app/assets/stylesheets/client/createSession.css.scss @@ -111,20 +111,4 @@ padding:10px; border-bottom:solid 1px #999; cursor:pointer; -} - - - -div[layout-id="createSession"] .icheckbuttons { - - margin-top:5px; - - div.iradio_minimal { - float:left; - } - - label { - float:left; - margin:0 10px 0 3px; - } -} +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/jamkazam.css.scss b/web/app/assets/stylesheets/client/jamkazam.css.scss index 341bd4d2e..819e8e9ef 100644 --- a/web/app/assets/stylesheets/client/jamkazam.css.scss +++ b/web/app/assets/stylesheets/client/jamkazam.css.scss @@ -460,4 +460,19 @@ div[layout-id=session], div[layout-id=ftue], .no-selection-range { -moz-user-select: none; -ms-user-select: none; user-select: none; -} \ No newline at end of file +} + + +.icheckbuttons { + + margin-top:5px; + + div.iradio_minimal { + float:left; + } + + label { + float:left; + margin:0 10px 0 3px; + } +} diff --git a/web/app/assets/stylesheets/client/recordingFinishedDialog.css.scss b/web/app/assets/stylesheets/client/recordingFinishedDialog.css.scss index a185d0dfa..986d140a8 100644 --- a/web/app/assets/stylesheets/client/recordingFinishedDialog.css.scss +++ b/web/app/assets/stylesheets/client/recordingFinishedDialog.css.scss @@ -1,12 +1,20 @@ #recording-finished-dialog { width:1000px; - + height:auto; div[purpose=description], div[purpose=is_public], div[purpose=is_downloadable] { margin-top:20px; } - label[for=is_downloadable], label[for=is_public] { + label[for=is_downloadable], label[for=is_public], label[for=playback-mode-preview-all], label[for=playback-mode-preview-me] { display:inline; } + + .recording-controls { + position:relative; + } + + .icheckbuttons { + margin-top:20px; + } } diff --git a/web/app/assets/stylesheets/client/session.css.scss b/web/app/assets/stylesheets/client/session.css.scss index b2c50d267..ad415a5da 100644 --- a/web/app/assets/stylesheets/client/session.css.scss +++ b/web/app/assets/stylesheets/client/session.css.scss @@ -491,6 +491,12 @@ table.vu td { background-color:#666; } +.session-mytracks { + .track-connection { + display:none; + } +} + .session-recordings { .track-connection { display:none; @@ -513,6 +519,10 @@ table.vu td { } } +#recording-finished-dialog .recording-controls { + display:block; +} + .voicechat { margin-top:10px; diff --git a/web/app/assets/stylesheets/playbackControls.css.scss b/web/app/assets/stylesheets/playbackControls.css.scss new file mode 100644 index 000000000..f0a0ab29a --- /dev/null +++ b/web/app/assets/stylesheets/playbackControls.css.scss @@ -0,0 +1,5 @@ +.recording-controls { + .playback-mode-buttons { + display:none; + } +} \ No newline at end of file diff --git a/web/app/controllers/api_claimed_recordings_controller.rb b/web/app/controllers/api_claimed_recordings_controller.rb index 2a657a5a7..a7c7dc013 100644 --- a/web/app/controllers/api_claimed_recordings_controller.rb +++ b/web/app/controllers/api_claimed_recordings_controller.rb @@ -24,13 +24,13 @@ class ApiClaimedRecordingsController < ApiController end def delete - begin - @claimed_recording.discard(current_user) - render :json => {}, :status => 204 + #begin + #@claimed_recording.discard(current_user) + #render :json => {}, :status => 204 # respond_with responder: ApiResponder, :status => 204 - rescue - render :json => { :message => "claimed_recording could not be deleted" }, :status => 403 - end + #rescue + #render :json => { :message => "claimed_recording could not be deleted" }, :status => 403 + #end end private diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb index 51aac0be0..d87f1f9c3 100644 --- a/web/app/controllers/api_recordings_controller.rb +++ b/web/app/controllers/api_recordings_controller.rb @@ -71,7 +71,6 @@ class ApiRecordingsController < ApiController # claim will create a claimed recording for the creator def claim claim = @recording.claim(current_user, params[:name], params[:description], Genre.find_by_id(params[:genre]), params[:is_public], params[:is_downloadable]) - claim.save if claim.errors.any? response.status = :unprocessable_entity @@ -83,8 +82,7 @@ class ApiRecordingsController < ApiController # discard will tell the server the user has no interest in the recording def discard - @recorded_tracks = @recording.recorded_tracks_for_user(current_user) - RecordedTrack.update(@recorded_tracks, :discard => true) + @recording.discard(current_user) render :json => {}, :status => 200 end diff --git a/web/app/views/api_claimed_recordings/show.rabl b/web/app/views/api_claimed_recordings/show.rabl index 121d08228..cb46530cd 100644 --- a/web/app/views/api_claimed_recordings/show.rabl +++ b/web/app/views/api_claimed_recordings/show.rabl @@ -15,13 +15,13 @@ child(:recording => :recording) { child(:mixes => :mixes) { attributes :id, :url, :is_completed } -} -child(:recorded_tracks => :recorded_tracks) { - attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id + child(:recorded_tracks => :recorded_tracks) { + attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id - child(:user => :user) { - attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url + child(:user => :user) { + attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url + } } } diff --git a/web/app/views/api_music_sessions/show.rabl b/web/app/views/api_music_sessions/show.rabl index 9d9f0511d..5170503ad 100644 --- a/web/app/views/api_music_sessions/show.rabl +++ b/web/app/views/api_music_sessions/show.rabl @@ -54,13 +54,13 @@ node(:claimed_recording, :if => lambda { |music_session| music_session.users.exi child(:mixes => :mixes) { attributes :id, :url, :is_completed } - } - child(:recorded_tracks => :recorded_tracks) { - attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id + child(:recorded_tracks => :recorded_tracks) { + attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id - child(:user => :user) { - attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url + child(:user => :user) { + attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url + } } } } diff --git a/web/app/views/api_recordings/show.rabl b/web/app/views/api_recordings/show.rabl index f0f15de2b..9fd83dfcf 100644 --- a/web/app/views/api_recordings/show.rabl +++ b/web/app/views/api_recordings/show.rabl @@ -3,12 +3,9 @@ object @recording attributes :id, :band, :created_at, :duration child(:recorded_tracks => :recorded_tracks) { - attributes :id, :client_id, :track_id, :user_id, :fully_uploaded, :url - child(:instrument => :instrument) { - attributes :id, :description - } + attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id + child(:user => :user) { attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url } } - diff --git a/web/app/views/clients/_play_controls.html.erb b/web/app/views/clients/_play_controls.html.erb index 5255576a4..7ee2042d4 100644 --- a/web/app/views/clients/_play_controls.html.erb +++ b/web/app/views/clients/_play_controls.html.erb @@ -25,5 +25,11 @@