$ = jQuery context = window context.JK ||= {}; context.JK.SyncViewer = class SyncViewer constructor: (@app) -> @EVENTS = context.JK.EVENTS @rest = context.JK.Rest() @logger = context.JK.logger @recordingUtils = context.JK.RecordingUtils @since = 0 @limit = 20 @showing = false @downloadCommandId = null @downloadMetadata = null @uploadCommandId = null @uploadMetadata = null @cleanupCommandId = null @cleanupMetadata = null init: () => @root = $($('#template-sync-viewer').html()) @inProgress = @root.find('.in-progress') @downloadProgress = @inProgress.find('.download-progress') @uploadProgress = @inProgress.find('.upload-progress') @list = @root.find('.list') @logList = @root.find('.log-list') @templateRecordedTrack = $('#template-sync-viewer-recorded-track') @templateRecordedBackingTrack = $('#template-sync-viewer-recorded-backing-track') @templateStreamMix = $('#template-sync-viewer-stream-mix') @templateMix = $('#template-sync-viewer-mix') @templateNoSyncs = $('#template-sync-viewer-no-syncs') @templateRecordingWrapperDetails = $('#template-sync-viewer-recording-wrapper-details') @templateHoverRecordedTrack = $('#template-sync-viewer-hover-recorded-track') @templateHoverRecordedBackingTrack = $('#template-sync-viewer-hover-recorded-backing-track') @templateHoverMix = $('#template-sync-viewer-hover-mix') @templateDownloadReset = $('#template-sync-viewer-download-progress-reset') @templateUploadReset = $('#template-sync-viewer-upload-progress-reset') @templateGenericCommand = $('#template-sync-viewer-generic-command') @templateRecordedTrackCommand = $('#template-sync-viewer-recorded-track-command') @templateRecordedBackingTrackCommand = $('#template-sync-viewer-recorded-backing-track-command') @templateLogItem = $('#template-sync-viewer-log-item') @tabSelectors = @root.find('.dialog-tabs .tab') @tabs = @root.find('.tab-content') @logBadge = @tabSelectors.find('.badge') @paginator = @root.find('.paginator-holder') @uploadStates = { unknown: 'unknown', too_many_upload_failures: 'too-many-upload-failures', me_upload_soon: 'me-upload-soon', them_upload_soon: 'them-upload-soon' missing: 'missing', me_uploaded: 'me-uploaded', them_uploaded: 'them-uploaded', not_mine: 'not-mine' } @clientStates = { unknown: 'unknown', too_many_uploads: 'too-many-downloads', hq: 'hq', sq: 'sq', missing: 'missing', discarded: 'discarded', not_mine: 'not-mine' } throw "no sync-viewer" if not @root.exists() throw "no in-progress" if not @inProgress.exists() throw "no list" if not @list.exists() throw "no recorded track template" if not @templateRecordedTrack.exists() throw "no stream mix template" if not @templateStreamMix.exists() throw "no empty syncs template" if not @templateNoSyncs.exists() $(document).on(@EVENTS.FILE_MANAGER_CMD_START, this.fileManagerCmdStart) $(document).on(@EVENTS.FILE_MANAGER_CMD_STOP, this.fileManagerCmdStop) $(document).on(@EVENTS.FILE_MANAGER_CMD_PROGRESS, this.fileManagerCmdProgress) $(document).on(@EVENTS.FILE_MANAGER_CMD_ASAP_UPDATE, this.fileManagerAsapCommandStatus) @tabSelectors.click((e) => $tabSelected = $(e.target).closest('a.tab') purpose = $tabSelected.attr('purpose') $otherTabSelectors = @tabSelectors.not('[purpose="' + purpose + '"]') $otherTabs = @tabs.not('[purpose="' + purpose + '"]') $tab = @tabs.filter('[purpose="' + purpose + '"]') $otherTabs.hide(); $tab.show() $otherTabSelectors.removeClass('selected'); $tabSelected.addClass('selected'); if purpose == 'log' @logBadge.hide() ) onShow: () => @showing = true this.load() onHide: () => @showing = false #$(document).off(@EVENTS.FILE_MANAGER_CMD_START, this.fileManagerCmdStart) #$(document).off(@EVENTS.FILE_MANAGER_CMD_STOP, this.fileManagerCmdStop) #$(document).off(@EVENTS.FILE_MANAGER_CMD_PROGRESS, this.fileManagerCmdProgress) getUserSyncs: (page) => @rest.getUserSyncs({since: page * @limit, limit: @limit}) .done(this.processUserSyncs) load: () => @list.empty() @since = 0 this.renderHeader() this.getUserSyncs(0) .done((response) => $paginator = context.JK.Paginator.create(response.total_entries, @limit, 0, this.getUserSyncs) @paginator.empty().append($paginator); ) renderHeader: () => recordingManagerState = context.jamClient.GetRecordingManagerState() if recordingManagerState.running @uploadProgress.removeClass('quiet paused busy') @downloadProgress.removeClass('quiet paused busy') if recordingManagerState.current_download @downloadProgress.addClass('busy') else @downloadProgress.addClass('quiet') @downloadProgress.find('.busy').empty() if recordingManagerState.current_upload @uploadProgress.addClass('busy') else @uploadProgress.addClass('quiet') @uploadProgress.find('.busy').empty() else @downloadProgress.removeClass('quiet paused busy').addClass('paused') @uploadProgress.removeClass('quiet paused busy').addClass('paused') @downloadProgress.find('.busy').empty() @uploadProgress.find('.busy').empty() updateMixState: ($mix) => serverInfo = $mix.data('server-info') mixInfo = @recordingUtils.createMixInfo(serverInfo) $mixState = $mix.find('.mix-state') $mixStateMsg = $mixState.find('.msg') $mixStateProgress = $mixState.find('.progress') $mixState.removeClass('still-uploading discarded unknown mixed mixing waiting-to-mix error stream-mix').addClass(mixInfo.mixStateClass).attr('data-state', mixInfo.mixState).data('mix-state', mixInfo) $mixStateMsg.text(mixInfo.mixStateMsg) $mixStateProgress.css('width', '0') updateStreamMixState: ($streamMix) => clientInfo = $streamMix.data('client-info') serverInfo = $streamMix.data('server-info') # determine client state clientStateMsg = 'UNKNOWN' clientStateClass = 'unknown' clientState = @clientStates.unknown if clientInfo? if clientInfo.local_state == 'COMPRESSED' clientStateMsg = 'STREAM QUALITY' clientStateClass = 'sq' clientState = @clientStates.sq else if clientInfo.local_state == 'UNCOMPRESSED' clientStateMsg = 'STREAM QUALITY' clientStateClass = 'sq' clientState = @clientStates.sq else if clientInfo.local_state == 'MISSING' clientStateMsg = 'MISSING' clientStateClass = 'missing' clientState = @clientStates.missing # determine upload state uploadStateMsg = 'UNKNOWN' uploadStateClass = 'unknown' uploadState = @uploadStates.unknown if !serverInfo.fully_uploaded if serverInfo.upload.too_many_upload_failures uploadStateMsg = 'UPLOAD FAILURE' uploadStateClass = 'error' uploadState = @uploadStates.too_many_upload_failures else if clientInfo? if clientInfo.local_state == 'UNCOMPRESSED' or clientInfo.local_state == 'COMPRESSED' uploadStateMsg = 'PENDING UPLOAD' uploadStateClass = 'upload-soon' uploadState = @uploadStates.me_upload_soon else uploadStateMsg = 'MISSING' uploadStateClass = 'missing' uploadState = @uploadStates.missing else uploadStateMsg = 'MISSING' uploadStateClass = 'missing' uploadState = @uploadStates.missing else uploadStateMsg = 'UPLOADED' uploadStateClass = 'uploaded' uploadState = @uploadStates.me_uploaded $clientState = $streamMix.find('.client-state') $clientStateMsg = $clientState.find('.msg') $clientStateProgress = $clientState.find('.progress') $uploadState = $streamMix.find('.upload-state') $uploadStateMsg = $uploadState.find('.msg') $uploadStateProgress = $uploadState.find('.progress') $clientState.removeClass('discarded missing sq hq unknown error').addClass(clientStateClass).attr('data-state', clientState).data('custom-class', clientStateClass) $clientStateMsg.text(clientStateMsg) $clientStateProgress.css('width', '0') $uploadState.removeClass('upload-soon error unknown missing uploaded').addClass(uploadStateClass).attr('data-state', uploadState).data('custom-class', uploadStateClass) $uploadStateMsg.text(uploadStateMsg) $uploadStateProgress.css('width', '0') updateTrackState: ($track) => clientInfo = $track.data('client-info') serverInfo = $track.data('server-info') myTrack = serverInfo.user.id == context.JK.currentUserId # determine client state clientStateMsg = 'UNKNOWN' clientStateClass = 'unknown' clientState = @clientStates.unknown if serverInfo.download.should_download if serverInfo.download.too_many_downloads clientStateMsg = 'EXCESS DOWNLOADS' clientStateClass = 'error' clientState = @clientStates.too_many_uploads else if clientInfo? if clientInfo.local_state == 'HQ' clientStateMsg = 'HIGHEST QUALITY' clientStateClass = 'hq' clientState = @clientStates.hq else clientStateMsg = 'STREAM QUALITY' clientStateClass = 'sq' clientState = @clientStates.sq else clientStateMsg = 'MISSING' clientStateClass = 'missing' clientState = @clientStates.missing else clientStateMsg = 'DISCARDED' clientStateClass = 'discarded' clientState = @clientStates.discarded # determine upload state uploadStateMsg = 'UNKNOWN' uploadStateClass = 'unknown' uploadState = @uploadStates.unknown if !serverInfo.fully_uploaded if serverInfo.upload.too_many_upload_failures uploadStateMsg = 'UPLOAD FAILURE' uploadStateClass = 'error' uploadState = @uploadStates.too_many_upload_failures else if myTrack if clientInfo? if clientInfo.local_state == 'HQ' uploadStateMsg = 'PENDING UPLOAD' uploadStateClass = 'upload-soon' uploadState = @uploadStates.me_upload_soon else uploadStateMsg = 'MISSING' uploadStateClass = 'missing' uploadState = @uploadStates.missing else uploadStateMsg = 'MISSING' uploadStateClass = 'missing' uploadState = @uploadStates.missing else uploadStateMsg = 'PENDING UPLOAD' uploadStateClass = 'upload-soon' uploadState = @uploadStates.them_upload_soon else uploadStateMsg = 'UPLOADED' uploadStateClass = 'uploaded' if myTrack uploadState = @uploadStates.me_uploaded else uploadState = @uploadStates.them_uploaded $clientState = $track.find('.client-state') $clientStateMsg = $clientState.find('.msg') $clientStateProgress = $clientState.find('.progress') $uploadState = $track.find('.upload-state') $uploadStateMsg = $uploadState.find('.msg') $uploadStateProgress = $uploadState.find('.progress') $clientState.removeClass('discarded missing sq hq unknown error').addClass(clientStateClass).attr('data-state', clientState).data('custom-class', clientStateClass) $clientStateMsg.text(clientStateMsg) $clientStateProgress.css('width', '0') $uploadState.removeClass('upload-soon error unknown missing uploaded').addClass(uploadStateClass).attr('data-state', uploadState).data('custom-class', uploadStateClass) $uploadStateMsg.text(uploadStateMsg) $uploadStateProgress.css('width', '0') # this allows us to make styling decisions based on the combination of both client and upload state. $track.addClass("clientState-#{clientStateClass}").addClass("uploadState-#{uploadStateClass}") $clientRetry = $clientState.find('.retry') $uploadRetry = $uploadState.find('.retry') if gon.isNativeClient # handle client state # only show RETRY button if you have a SQ or if it's missing, and it's been uploaded already if (clientState == @clientStates.sq or clientState == @clientStates.missing) and (uploadState == @uploadStates.me_uploaded or uploadState == @uploadStates.them_uploaded) $clientRetry.show() else $clientRetry.hide() # only show RETRY button if you have the HQ track, it's your track, and the server doesn't yet have it if myTrack and @clientStates.hq and (uploadState == @uploadStates.error or uploadState == @uploadStates.me_upload_soon) $uploadRetry.show() else $uploadRetry.hide() else $clientRetry.hide() $uploadRetry.hide() updateBackingTrackState: ($track) => clientInfo = $track.data('client-info') serverInfo = $track.data('server-info') myTrack = serverInfo.user.id == context.JK.currentUserId # determine client state clientStateMsg = 'UNKNOWN' clientStateClass = 'unknown' clientState = @clientStates.unknown if serverInfo.mine if serverInfo.download.should_download if serverInfo.download.too_many_downloads clientStateMsg = 'EXCESS DOWNLOADS' clientStateClass = 'error' clientState = @clientStates.too_many_uploads else if clientInfo? if clientInfo.local_state == 'HQ' clientStateMsg = 'HIGHEST QUALITY' clientStateClass = 'hq' clientState = @clientStates.hq else if clientInfo.local_state == 'MISSING' clientStateMsg = 'MISSING' clientStateClass = 'missing' clientState = @clientStates.missing else clientStateMsg = 'MISSING' clientStateClass = 'missing' clientState = @clientStates.missing else clientStateMsg = 'DISCARDED' clientStateClass = 'discarded' clientState = @clientStates.discarded else clientStateMsg = 'NOT MINE' clientStateClass = 'not_mine' clientState = @clientStates.not_mine # determine upload state uploadStateMsg = 'UNKNOWN' uploadStateClass = 'unknown' uploadState = @uploadStates.unknown if serverInfo.mine if !serverInfo.fully_uploaded if serverInfo.upload.too_many_upload_failures uploadStateMsg = 'UPLOAD FAILURE' uploadStateClass = 'error' uploadState = @uploadStates.too_many_upload_failures else if myTrack if clientInfo? if clientInfo.local_state == 'HQ' uploadStateMsg = 'PENDING UPLOAD' uploadStateClass = 'upload-soon' uploadState = @uploadStates.me_upload_soon else uploadStateMsg = 'MISSING' uploadStateClass = 'missing' uploadState = @uploadStates.missing else uploadStateMsg = 'MISSING' uploadStateClass = 'missing' uploadState = @uploadStates.missing else uploadStateMsg = 'PENDING UPLOAD' uploadStateClass = 'upload-soon' uploadState = @uploadStates.them_upload_soon else uploadStateMsg = 'UPLOADED' uploadStateClass = 'uploaded' if myTrack uploadState = @uploadStates.me_uploaded else uploadState = @uploadStates.them_uploaded else uploadStateMsg = 'NOT MINE' uploadStateClass = 'not_mine' uploadState = @uploadStates.not_mine $clientState = $track.find('.client-state') $clientStateMsg = $clientState.find('.msg') $clientStateProgress = $clientState.find('.progress') $uploadState = $track.find('.upload-state') $uploadStateMsg = $uploadState.find('.msg') $uploadStateProgress = $uploadState.find('.progress') $clientState.removeClass('discarded missing hq unknown error not-mine').addClass(clientStateClass).attr('data-state', clientState).data('custom-class', clientStateClass) $clientStateMsg.text(clientStateMsg) $clientStateProgress.css('width', '0') $uploadState.removeClass('upload-soon error unknown missing uploaded not-mine').addClass(uploadStateClass).attr('data-state', uploadState).data('custom-class', uploadStateClass) $uploadStateMsg.text(uploadStateMsg) $uploadStateProgress.css('width', '0') # this allows us to make styling decisions based on the combination of both client and upload state. $track.addClass("clientState-#{clientStateClass}").addClass("uploadState-#{uploadStateClass}") $clientRetry = $clientState.find('.retry') $uploadRetry = $uploadState.find('.retry') if gon.isNativeClient # handle client state # only show RETRY button if you have a SQ or if it's missing, and it's been uploaded already if (clientState == @clientStates.missing) and (uploadState == @uploadStates.me_uploaded or uploadState == @uploadStates.them_uploaded) $clientRetry.show() else $clientRetry.hide() # only show RETRY button if you have the HQ track, it's your track, and the server doesn't yet have it if myTrack and @clientStates.hq and (uploadState == @uploadStates.error or uploadState == @uploadStates.me_upload_soon) $uploadRetry.show() else $uploadRetry.hide() else $clientRetry.hide() $uploadRetry.hide() associateClientInfo: (recording) => for clientInfo in recording.local_tracks $track = @list.find(".recorded-track[data-recording-id='#{recording.recording_id}'][data-client-track-id='#{clientInfo.client_track_id}']") $track.data('client-info', clientInfo) $track.data('total-size', recording.size) for clientInfo in recording.backing_tracks $track = @list.find(".recorded-backing-track[data-recording-id='#{recording.recording_id}'][data-client-track-id='#{clientInfo.client_track_id}']") $track.data('client-info', clientInfo) $track.data('total-size', recording.size) $track = @list.find(".mix[data-recording-id='#{recording.recording_id}']") $track.data('client-info', recording.mix) $track.data('total-size', recording.size) $track = @list.find(".stream-mix[data-recording-id='#{recording.recording_id}']") $track.data('client-info', recording.stream_mix) $track.data('total-size', recording.size) displayStreamMixHover: ($streamMix) => $clientState = $streamMix.find('.client-state') $clientStateMsg = $clientState.find('.msg') clientStateClass = $clientState.data('custom-class') clientState = $clientState.attr('data-state') clientInfo = $streamMix.data('client-info') $uploadState = $streamMix.find('.upload-state') $uploadStateMsg = $uploadState.find('.msg') uploadStateClass = $uploadState.data('custom-class') uploadState = $uploadState.attr('data-state') serverInfo = $streamMix.data('server-info') # decide on special case strings first summary = '' if clientState == @clientStates.sq && uploadState == @uploadStates.me_upload_soon summary = "We will attempt to upload your stream mix so that others can hear the recording on the JamKazam site, even before the final mix is done. It will upload shortly." else if clientState == @clientStates.sq && uploadState == @uploadStates.me_uploaded # we have the SQ version, and the other user has uploaded the HQ version... it's coming soon! summary = "We already uploaded your stream mix so that others can hear the recording on the JamKazam site, even before the final mix is done. Since it's uploaded, there is nothing else left to do with the stream mix... you're all done!" else if clientState == @clientStates.missing summary = "You do not have the stream mix on your computer anymore. This can happen if you change the computer that you run JamKazam on. It's important to note that once a final mix for the recording is available, there is no value in the stream mix." clientStateDefinition = switch clientState when @clientStates.sq then "The stream mix is always STREAM QUALITY, because it's the version of the recording that you heard in your earphones as you made the recording." when @clientStates.missing then "MISSING means you do not have the stream mix anymore." else 'There is no help for this state' uploadStateDefinition = switch uploadState when @uploadStates.too_many_upload_failures then "Failed attempts at uploading this stream mix has happened an unusually large times. No more uploads will be attempted." when @uploadStates.me_upload_soon then "PENDING UPLOAD means your JamKazam application will upload this stream mix soon." when @uploadStates.me_uploaded then "UPLOADED means you have already uploaded this stream mix." when @uploadStates.missing then "MISSING means your JamKazam application does not have this stream mix, and the server does not either." context._.template(@templateHoverRecordedTrack.html(), {summary: summary, clientStateDefinition: clientStateDefinition, uploadStateDefinition: uploadStateDefinition, clientStateMsg: $clientStateMsg.text(), uploadStateMsg: $uploadStateMsg.text(), clientStateClass: clientStateClass, uploadStateClass: uploadStateClass} {variable: 'data'}) displayTrackHover: ($recordedTrack) => $clientState = $recordedTrack.find('.client-state') $clientStateMsg = $clientState.find('.msg') clientStateClass = $clientState.data('custom-class') clientState = $clientState.attr('data-state') clientInfo = $recordedTrack.data('client-info') $uploadState = $recordedTrack.find('.upload-state') $uploadStateMsg = $uploadState.find('.msg') uploadStateClass = $uploadState.data('custom-class') uploadState = $uploadState.attr('data-state') serverInfo = $recordedTrack.data('server-info') # decide on special case strings first summary = '' if clientState == @clientStates.sq && uploadState == @uploadStates.them_upload_soon # we have the SQ version, and the other user hasn't uploaded it yet summary = "#{serverInfo.user.name} has not yet uploaded the high-quality version of this track. Once he or she does, JamKazam will download it and replace your stream-quality version." else if clientState == @clientStates.missing && uploadState == @uploadStates.them_upload_soon # we don't have any version of the track at all, and the other user hasn't uploaded it yet summary = "#{serverInfo.user.name} has not yet uploaded the high-quality version of this track. Once he or she does, JamKazam will download it and this track will no longer be missing." else if clientState == @clientStates.sq && uploadState == @uploadStates.them_uploaded # we have the SQ version, and the other user has uploaded the HQ version... it's coming soon! summary = "#{serverInfo.user.name} has uploaded the high-quality version of this track. JamKazam will soon download it and replace your stream-quality version." else if clientState == @clientStates.missing && uploadState == @uploadStates.them_uploaded # we have no version of the track at all, and the other user has uploaded the HQ version... it's coming soon! summary = "#{serverInfo.user.name} has uploaded the high-quality version of this track. JamKazam will soon restore it and then this track will no longer be missing." else if clientState == @clientStates.sq && uploadState == @uploadStates.me_uploaded # we have the SQ version, and the other user has uploaded the HQ version... it's coming soon! summary = "You have previously uploaded the high-quality version of this track. JamKazam will soon restore it and replace your stream-quality version." else if clientState == @clientStates.missing && uploadState == @uploadStates.me_uploaded # we have no version of the track at all, and the other user has uploaded the HQ version... it's coming soon! summary = "You have previously uploaded the high-quality version of this track. JamKazam will soon restore it and then this track will no longer be missing." else if clientState == @clientStates.discarded && (uploadState == @uploadStates.me_uploaded or uploadState == @uploadStates.them_uploaded) # we decided not to keep the recording... so it's important to clarify why they are seeing it at all summary = "When this recording was made, you elected to not keep it. JamKazam already uploaded your high-quality tracks for the recording, because at least one other person decided to keep the recording and needs your tracks to make a high-quality mix." else if clientState == @clientStates.discarded # we decided not to keep the recording... so it's important to clarify why they are seeing it at all summary = "When this recording was made, you elected to not keep it. JamKazam will still try to upload your high-quality tracks for the recording, because at least one other person decided to keep the recording and needs your tracks to make a high-quality mix." else if clientState == @clientStates.hq and ( uploadState == @uploadStates.them_uploaded or uploadState == @uploadStates.me_uploaded ) summary = "Both you and the JamKazam server have the high-quality version of this track. Once all the other tracks for this recording are also synchronized, then the final mix can be made." clientStateDefinition = switch clientState when @clientStates.too_many_downloads then "This track has been downloaded an unusually large number of times. No more downloads are allowed." when @clientStates.hq then "HIGHEST QUALITY means you have the original version of this track, as recorded by the user that made it." when @clientStates.sq then "STREAM QUALITY means you have the version of the track that you received over the internet in real-time." when @clientStates.missing then "MISSING means you do not have this track anymore." when @clientStates.discarded then "DISCARDED means you chose to not keep this recording when the recording was over." else 'There is no help for this state' uploadStateDefinition = switch uploadState when @uploadStates.too_many_upload_failures then "Failed attempts at uploading this track has happened an unusually large times. No more uploads will be attempted." when @uploadStates.me_upload_soon then "PENDING UPLOAD means your JamKazam application will upload this track soon." when @uploadStates.them_up_soon then "PENDING UPLOAD means #{serverInfo.user.name} will upload this track soon." when @uploadStates.me_uploaded then "UPLOADED means you have already uploaded this track." when @uploadStates.them_uploaded then "UPLOADED means #{serverInfo.user.name} has already uploaded this track." when @uploadStates.missing then "MISSING means your JamKazam application does not have this track, and the server does not either." context._.template(@templateHoverRecordedTrack.html(), {summary: summary, clientStateDefinition: clientStateDefinition, uploadStateDefinition: uploadStateDefinition, clientStateMsg: $clientStateMsg.text(), uploadStateMsg: $uploadStateMsg.text(), clientStateClass: clientStateClass, uploadStateClass: uploadStateClass} {variable: 'data'}) displayBackingTrackHover: ($recordedTrack) => $clientState = $recordedTrack.find('.client-state') $clientStateMsg = $clientState.find('.msg') clientStateClass = $clientState.data('custom-class') clientState = $clientState.attr('data-state') clientInfo = $recordedTrack.data('client-info') $uploadState = $recordedTrack.find('.upload-state') $uploadStateMsg = $uploadState.find('.msg') uploadStateClass = $uploadState.data('custom-class') uploadState = $uploadState.attr('data-state') serverInfo = $recordedTrack.data('server-info') # decide on special case strings first summary = '' if clientState == @clientStates.not_mine && @uploadStates.them_uploaded # this is not our backing track summary = "#{serverInfo.user.name} opened this backing track. Due to legal concerns, we can not distribute it to you." else if clientState == @clientStates.not_mine && @uploadStates.them_upload_soon # this is not our backing track summary = "#{serverInfo.user.name} has not yet uploaded their backing track." else if clientState == @clientStates.missing && uploadState == @uploadStates.me_uploaded # we have no version of the track at all, and the other user has uploaded the HQ version... it's coming soon! summary = "You have previously uploaded the high-quality version of this track. JamKazam will soon restore it and then this backing track will no longer be missing." else if clientState == @clientStates.discarded && (uploadState == @uploadStates.me_uploaded or uploadState == @uploadStates.them_uploaded) # we decided not to keep the recording... so it's important to clarify why they are seeing it at all summary = "When this recording was made, you elected to not keep it. JamKazam already uploaded your high-quality backing track for the recording, because at least one other person decided to keep the recording and needs your backing track to make a high-quality mix." else if clientState == @clientStates.discarded # we decided not to keep the recording... so it's important to clarify why they are seeing it at all summary = "When this recording was made, you elected to not keep it. JamKazam will still try to upload your high-quality backing track for the recording, because at least one other person decided to keep the recording and needs your backing track to make a high-quality mix." else if clientState == @clientStates.hq and ( uploadState == @uploadStates.me_uploaded ) summary = "Both you and the JamKazam server have the high-quality version of this track. Once all the other tracks for this recording are also synchronized, then the final mix can be made." clientStateDefinition = switch clientState when @clientStates.too_many_downloads then "This backing track has been downloaded an unusually large number of times. No more downloads are allowed." when @clientStates.hq then "HIGHEST QUALITY means you have the original version of this backing track." when @clientStates.missing then "MISSING means you do not have this backing track anymore." when @clientStates.discarded then "DISCARDED means you chose to not keep this recording when the recording was over." when @clientStates.not_mine then "NOT MINE means someone else opened and played this backing track." else 'There is no help for this state' uploadStateDefinition = switch uploadState when @uploadStates.too_many_upload_failures then "Failed attempts at uploading this backing track has happened an unusually large times. No more uploads will be attempted." when @uploadStates.me_upload_soon then "PENDING UPLOAD means your JamKazam application will upload this backing track soon." when @uploadStates.them_up_soon then "PENDING UPLOAD means #{serverInfo.user.name} will upload this backing track soon." when @uploadStates.me_uploaded then "UPLOADED means you have already uploaded this backing track." when @uploadStates.them_uploaded then "UPLOADED means #{serverInfo.user.name} has already uploaded this backing track." when @uploadStates.missing then "MISSING means your JamKazam application does not have this backing track, and the server does not either." when @uploadStates.not_mine then "NOT MINE means someone else opened and played this backing track." context._.template(@templateHoverRecordedBackingTrack.html(), {summary: summary, clientStateDefinition: clientStateDefinition, uploadStateDefinition: uploadStateDefinition, clientStateMsg: $clientStateMsg.text(), uploadStateMsg: $uploadStateMsg.text(), clientStateClass: clientStateClass, uploadStateClass: uploadStateClass} {variable: 'data'}) onTrackHoverOfStateIndicator: () -> $recordedTrack = $(this).closest('.recorded-track.sync') self = $recordedTrack.data('sync-viewer') self.displayTrackHover($recordedTrack) onBackingTrackHoverOfStateIndicator: () -> $recordedTrack = $(this).closest('.recorded-backing-track.sync') self = $recordedTrack.data('sync-viewer') self.displayBackingTrackHover($recordedTrack) onStreamMixHover: () -> $streamMix = $(this).closest('.stream-mix.sync') self = $streamMix.data('sync-viewer') self.displayStreamMixHover($streamMix) resetDownloadProgress: () => @downloadProgress resetUploadProgress: () => @uploadProgress sendCommand: ($retry, cmd) => if context.SessionStore.inSession() context.JK.ackBubble($retry, 'sync-viewer-paused', {}, {offsetParent: $retry.closest('.dialog')}) else context.jamClient.OnTrySyncCommand(cmd) context.JK.ackBubble($retry, 'sync-viewer-retry', {}, {offsetParent: $retry.closest('.dialog')}) retryDownloadRecordedTrack: (e) => $retry = $(e.target) $track = $retry.closest('.recorded-track') serverInfo = $track.data('server-info') this.sendCommand($retry, { type: 'recorded_track', action: 'download' queue: 'download', recording_id: serverInfo.recording_id track_id: serverInfo.client_track_id }) return false retryUploadRecordedTrack: (e) => $retry = $(e.target) $track = $retry.closest('.recorded-track') serverInfo = $track.data('server-info') this.sendCommand($retry, { type: 'recorded_track', action: 'upload' queue: 'upload', recording_id: serverInfo.recording_id track_id: serverInfo.client_track_id }) return false retryDownloadRecordedBackingTrack: (e) => $retry = $(e.target) $track = $retry.closest('.recorded-backing-track') serverInfo = $track.data('server-info') console.log("track serverInfo", $track, serverInfo) this.sendCommand($retry, { type: 'recorded_backing_track', action: 'download' queue: 'download', recording_id: serverInfo.recording_id track_id: serverInfo.client_track_id }) return false retryUploadRecordedBackingTrack: (e) => $retry = $(e.target) $track = $retry.closest('.recorded-backing-track') serverInfo = $track.data('server-info') console.log("track serverInfo", $track, serverInfo) this.sendCommand($retry, { type: 'recorded_backing_track', action: 'upload' queue: 'upload', recording_id: serverInfo.recording_id track_id: serverInfo.client_track_id }) return false createMix: (userSync) => recordingInfo = null if userSync == 'fake' recordingInfo = arguments[1] # sift through the recorded_tracks in here; if they are marked discarded, then we can also mark this one discarded too discarded = true for claim in recordingInfo.claimed_recordings if claim.user_id == context.JK.currentUserId discarded = false break userSync = { recording_id: recordingInfo.id, duration: recordingInfo.duration, fake:true, discarded: discarded } $mix = $(context._.template(@templateMix.html(), userSync, {variable: 'data'})) else $mix = $(context._.template(@templateMix.html(), userSync, {variable: 'data'})) $mix.data('server-info', userSync) $mix.data('sync-viewer', this) $mix.data('view-context', 'sync') $mixState = $mix.find('.mix-state') this.updateMixState($mix) context.JK.hoverBubble($mixState, @recordingUtils.onMixHover, {width:'450px', closeWhenOthersOpen: true, positions:['left'], trigger:['hoverIntent', 'none']}) $mix createTrack: (userSync) => $track = $(context._.template(@templateRecordedTrack.html(), userSync, {variable: 'data'})) $track.data('server-info', userSync) $track.data('sync-viewer', this) $clientState = $track.find('.client-state') $uploadState = $track.find('.upload-state') $clientStateRetry = $clientState.find('.retry') $clientStateRetry.click(this.retryDownloadRecordedTrack) $uploadStateRetry = $uploadState.find('.retry') $uploadStateRetry.click(this.retryUploadRecordedTrack) context.JK.bindHoverEvents($track) context.JK.bindInstrumentHover($track, {positions:['top'], shrinkToFit: true}); context.JK.hoverBubble($clientState, this.onTrackHoverOfStateIndicator, {width:'450px', closeWhenOthersOpen: true, positions:['left']}) context.JK.hoverBubble($uploadState, this.onTrackHoverOfStateIndicator, {width:'450px', closeWhenOthersOpen: true, positions:['right']}) $clientState.addClass('is-native-client') if gon.isNativeClient $uploadState.addClass('is-native-client') if gon.isNativeClient $track createBackingTrack: (userSync) => $track = $(context._.template(@templateRecordedBackingTrack.html(), userSync, {variable: 'data'})) $track.data('server-info', userSync) $track.data('sync-viewer', this) $clientState = $track.find('.client-state') $uploadState = $track.find('.upload-state') $clientStateRetry = $clientState.find('.retry') $clientStateRetry.click(this.retryDownloadRecordedBackingTrack) $uploadStateRetry = $uploadState.find('.retry') $uploadStateRetry.click(this.retryUploadRecordedBackingTrack) context.JK.bindHoverEvents($track) context.JK.bindInstrumentHover($track, {positions:['top'], shrinkToFit: true}); context.JK.hoverBubble($clientState, this.onBackingTrackHoverOfStateIndicator, {width:'450px', closeWhenOthersOpen: true, positions:['left']}) context.JK.hoverBubble($uploadState, this.onBackingTrackHoverOfStateIndicator, {width:'450px', closeWhenOthersOpen: true, positions:['right']}) $clientState.addClass('is-native-client') if gon.isNativeClient $uploadState.addClass('is-native-client') if gon.isNativeClient $track createStreamMix: (userSync) => $track = $(context._.template(@templateStreamMix.html(), userSync, {variable: 'data'})) $track.data('server-info', userSync) $track.data('sync-viewer', this) $clientState = $track.find('.client-state') $uploadState = $track.find('.upload-state') $uploadState.find('.retry').click(this.retryUploadRecordedTrack) context.JK.hoverBubble($clientState, this.onStreamMixHover, {width:'450px', closeWhenOthersOpen: true, positions:['left']}) context.JK.hoverBubble($uploadState, this.onStreamMixHover, {width:'450px', closeWhenOthersOpen: true, positions:['right']}) $clientState.addClass('is-native-client') if gon.isNativeClient $uploadState.addClass('is-native-client') if gon.isNativeClient $track openVideo: (e) => $link = $(e.target) recordingId = $link.closest('.details').attr('data-recording-id') if !context.jamClient.openVideo(recordingId) @app.layout.notify({title: 'No Video Found', text: 'Did you delete this recording earlier from your computer?'}) return false exportRecording: (e) => $export = $(e.target) if context.SessionStore.inSession() context.JK.ackBubble($export, 'sync-viewer-paused', {}, {offsetParent: $export.closest('.dialog')}) return recordingId = $export.closest('.details').attr('data-recording-id') if !recordingId? or recordingId == "" throw "exportRecording can't find data-recording-id" cmd = { type: 'export_recording', action: 'export', queue: 'upload', recording_id: recordingId} logger.debug("enqueueing export") context.jamClient.OnTrySyncCommand(cmd) return false; deleteRecording: (e) => $delete = $(e.target) if context.SessionStore.inSession() context.JK.ackBubble($delete, 'sync-viewer-paused', {}, {offsetParent: $delete.closest('.dialog')}) return $details = $delete.closest('.details') recordingId = $details.attr('data-recording-id') if !recordingId? or recordingId == "" throw "deleteRecording can't find data-recording-id" context.JK.Banner.showYesNo({ title: "Confirm Deletion", html: "Are you sure you want to delete this recording?", yes: => @rest.deleteRecordingClaim(recordingId).done((response)=> cmd = { type: 'recording_directory', action: 'delete', queue: 'cleanup', recording_id: recordingId} # now check if the sync is gone entirely, allowing us to delete it from the UI @rest.getUserSync({user_sync_id: recordingId}).done((userSync) => # the user sync is still here. tell user it'll be done as soon as they've uploaded their files context.JK.ackBubble($delete, 'file-sync-delayed-deletion', {}, {offsetParent: $delete.closest('.dialog')}) ) .fail((xhr) => if xhr.status == 404 # the userSync is gone; remove from file manager dynamically $recordingHolder = $details.closest('.recording-holder') $recordingHolder.slideUp() else @app.ajaxError(arguments) ) context.jamClient.OnTrySyncCommand(cmd) ) .fail(@app.ajaxError) }) return false; displaySize: (size) => # size is in bytes. divide by million, anxosd round to one decimal place megs = Math.round(size * 10 / (1024 * 1024) ) / 10 "#{megs}M" createRecordingWrapper: ($toWrap, recordingInfo) => totalSize = $($toWrap.get(0)).data('total-size') recordingInfo.recording_landing_url = "/recordings/#{recordingInfo.id}" recordingInfo.totalSize = this.displaySize(totalSize) recordingInfo.claimedRecordingId = recordingInfo.my?.id $wrapperDetails = $(context._.template(@templateRecordingWrapperDetails.html(), recordingInfo, {variable: 'data'})) $wrapper = $('
') $toWrap.wrapAll($wrapper) $wrapper = $toWrap.closest('.recording-holder') $wrapperDetails.prependTo($wrapper) $mix = $wrapper.find('.mix.sync') if $mix.length == 0 # create a virtual mix so that the UI is consistent $wrapper.append(this.createMix('fake', recordingInfo)) if recordingInfo.video $wrapper.find('a.open-video').click(this.openVideo).removeClass('hidden') $wrapper.find('a.export').click(this.exportRecording) $wrapper.find('a.delete').click(this.deleteRecording) separateByRecording: () => $recordedTracks = @list.find('.sync') currentRecordingId = null; queue = $([]); for recordedTrack in $recordedTracks $recordedTrack = $(recordedTrack) recordingId = $recordedTrack.attr('data-recording-id') if recordingId != currentRecordingId if queue.length > 0 this.createRecordingWrapper(queue, $(queue.get(0)).data('server-info').recording) queue = $([]) currentRecordingId = recordingId queue = queue.add(recordedTrack) if queue.length > 0 this.createRecordingWrapper(queue, $(queue.get(0)).data('server-info').recording) processUserSyncs: (response) => @list.empty() # check if no entries if @since == 0 and response.entries.length == 0 @list.append(context._.template(@templateNoSyncs.html(), {}, {variable: 'data'})) else recordings = {} # collect all unique recording for userSync in response.entries if userSync.type == 'recorded_track' @list.append(this.createTrack(userSync)) if userSync.type == 'recorded_backing_track' @list.append(this.createBackingTrack(userSync)) else if userSync.type == 'mix' @list.append(this.createMix(userSync)) else if userSync.type == 'stream_mix' @list.append(this.createStreamMix(userSync)) recordings[userSync.recording_id] = userSync.recording recordingsToResolve = [] # resolve each track against backend data: for recording_id, recording of recordings recordingsToResolve.push(recording) clientRecordings = context.jamClient.GetLocalRecordingState(recordings: recordingsToResolve) if clientRecordings.error? alert(clientRecordings.error) else this.associateClientInfo(turp) for turp in clientRecordings.recordings for track in @list.find('.recorded-track.sync') this.updateTrackState($(track)) for track in @list.find('.recorded-backing-track.sync') this.updateBackingTrackState($(track)) for streamMix in @list.find('.stream-mix.sync') this.updateStreamMixState($(streamMix)) this.separateByRecording() @since = response.next resolveTrack: (commandMetadata) => recordingId = commandMetadata['recording_id'] clientTrackId = commandMetadata['track_id'] matchingTrack = @list.find(".recorded-track[data-recording-id='#{recordingId}'][data-client-track-id='#{clientTrackId}']") if matchingTrack.length == 0 return @rest.getRecordedTrack({recording_id: recordingId, track_id: clientTrackId}) else deferred = $.Deferred(); deferred.resolve(matchingTrack.data('server-info')) return deferred resolveBackingTrack: (commandMetadata) => recordingId = commandMetadata['recording_id'] clientTrackId = commandMetadata['track_id'] matchingTrack = @list.find(".recorded-backing-track[data-recording-id='#{recordingId}'][data-client-track-id='#{clientTrackId}']") if matchingTrack.length == 0 return @rest.getRecordedBackingTrack({recording_id: recordingId, track_id: clientTrackId}) else deferred = $.Deferred(); deferred.resolve(matchingTrack.data('server-info')) return deferred renderFullUploadRecordedTrack: (serverInfo) => $track = $(context._.template(@templateRecordedTrackCommand.html(), $.extend(serverInfo, {action:'UPLOADING'}), {variable: 'data'})) $busy = @uploadProgress.find('.busy') $busy.empty().append($track) @uploadProgress.find('.progress').css('width', '0%') renderFullDownloadRecordedTrack: (serverInfo) => $track = $(context._.template(@templateRecordedTrackCommand.html(), $.extend(serverInfo, {action:'DOWNLOADING'}), {variable: 'data'})) $busy = @downloadProgress.find('.busy') $busy.empty().append($track) @downloadProgress.find('.progress').css('width', '0%') renderFullUploadRecordedBackingTrack: (serverInfo) => $track = $(context._.template(@templateRecordedBackingTrackCommand.html(), $.extend(serverInfo, {action:'UPLOADING'}), {variable: 'data'})) $busy = @uploadProgress.find('.busy') $busy.empty().append($track) @uploadProgress.find('.progress').css('width', '0%') renderFullDownloadRecordedBackingTrack: (serverInfo) => $track = $(context._.template(@templateRecordedBackingTrackCommand.html(), $.extend(serverInfo, {action:'DOWNLOADING'}), {variable: 'data'})) $busy = @downloadProgress.find('.busy') $busy.empty().append($track) @downloadProgress.find('.progress').css('width', '0%') # this will either show a generic placeholder, or immediately show the whole track renderDownloadRecordedTrack: (commandId, commandMetadata) => # try to find the info in the list; if we can't find it, then resolve it deferred = this.resolveTrack(commandMetadata) if deferred.state() == 'pending' this.renderGeneric(commandId, 'download', commandMetadata) deferred.done(this.renderFullDownloadRecordedTrack).fail(()=> @logger.error("unable to fetch recorded_track info") ) renderUploadRecordedTrack: (commandId, commandMetadata) => # try to find the info in the list; if we can't find it, then resolve it deferred = this.resolveTrack(commandMetadata) if deferred.state() == 'pending' this.renderGeneric(commandId, 'upload', commandMetadata) deferred.done(this.renderFullUploadRecordedTrack).fail(()=> @logger.error("unable to fetch recorded_track info") ) # this will either show a generic placeholder, or immediately show the whole track renderDownloadRecordedBackingTrack: (commandId, commandMetadata) => # try to find the info in the list; if we can't find it, then resolve it deferred = this.resolveBackingTrack(commandMetadata) if deferred.state() == 'pending' this.renderGeneric(commandId, 'download', commandMetadata) deferred.done(this.renderFullDownloadRecordedBackingTrack).fail(()=> @logger.error("unable to fetch recorded_backing_track info") ) renderUploadRecordedBackingTrack: (commandId, commandMetadata) => # try to find the info in the list; if we can't find it, then resolve it deferred = this.resolveBackingTrack(commandMetadata) if deferred.state() == 'pending' this.renderGeneric(commandId, 'upload', commandMetadata) deferred.done(this.renderFullUploadRecordedBackingTrack).fail(()=> @logger.error("unable to fetch recorded_backing_track info") ) renderGeneric: (commandId, category, commandMetadata) => commandMetadata.displayType = this.displayName(commandMetadata) $generic = $(context._.template(@templateGenericCommand.html(), commandMetadata, {variable: 'data'})) if category == 'download' $busy = @downloadProgress.find('.busy') $busy.empty().append($generic) else if category == 'upload' $busy = @uploadProgress.find('.busy') $busy.empty().append($generic) else @logger.error("unknown category #{category}") renderStartCommand: (commandId, commandType, commandMetadata) => #console.log("renderStartCommand", arguments) unless commandMetadata? managerState = context.jamClient.GetRecordingManagerState() if commandType == 'download' commandMetadata = managerState.current_download else if commandType == 'upload' commandMetadata = managerState.current_upload else @logger.error("unknown commandType #{commandType}") unless commandMetadata? # we still have no metadata. we have to give up @logger.error("no metadata found for current command #{commandId} #{commandType}. bailing out") return if commandMetadata.queue == 'download' @downloadCommandId = commandId @downloadMetadata = commandMetadata @downloadProgress.removeClass('quiet paused busy') @downloadProgress.addClass('busy') if commandMetadata.type == 'recorded_track' and commandMetadata.action == 'download' this.renderDownloadRecordedTrack(commandId, commandMetadata) else if commandMetadata.type == 'recorded_backing_track' and commandMetadata.action == 'download' this.renderDownloadRecordedBackingTrack(commandId, commandMetadata) else this.renderGeneric(commandId, 'download', commandMetadata) else if commandMetadata.queue == 'upload' @uploadCommandId = commandId @uploadMetadata = commandMetadata @uploadProgress.removeClass('quiet paused busy') @uploadProgress.addClass('busy') if commandMetadata.type == 'recorded_track' and commandMetadata.action == 'upload' this.renderUploadRecordedTrack(commandId, commandMetadata) else if commandMetadata.type == 'recorded_backing_track' and commandMetadata.action == 'upload' this.renderUploadRecordedBackingTrack(commandId, commandMetadata) else this.renderGeneric(commandId, 'upload', commandMetadata) else if commandMetadata.queue == 'cleanup' @cleanupCommandId = commandId @cleanupMetadata = commandMetadata renderSingleRecording: (userSyncs) => return if userSyncs.entries.length == 0 clientRecordings = context.jamClient.GetLocalRecordingState(recordings: [userSyncs.entries[0].recording]) for userSync in userSyncs.entries if userSync.type == 'recorded_track' $track = @list.find(".sync[data-id='#{userSync.id}']") continue if $track.length == 0 $track.data('server-info', userSync) this.associateClientInfo(clientRecordings.recordings[0]) this.updateTrackState($track) else if userSync.type == 'recorded_backing_track' $track = @list.find(".sync[data-id='#{userSync.id}']") continue if $track.length == 0 $track.data('server-info', userSync) this.associateClientInfo(clientRecordings.recordings[0]) this.updateBackingTrackState($track) else if userSync.type == 'mix' # check if there is a virtual mix 1st; if so, update it $mix = @list.find(".mix.virtual[data-recording-id='#{userSync.recording.id}']") if $mix.length == 0 $mix = @list.find(".sync[data-id='#{userSync.id}']") continue if $mix.length == 0 $newMix = this.createMix(userSync) this.associateClientInfo(clientRecordings.recordings[0]) $mix.replaceWith($newMix) else if userSync.type == 'stream_mix' $streamMix = @list.find(".sync[data-id='#{userSync.id}']") continue if $streamMix.length == 0 $streamMix.data('server-info', userSync) this.associateClientInfo(clientRecordings.recordings[0]) this.updateStreamMixState($streamMix) updateSingleRecording: (recording_id) => @rest.getUserSyncs({recording_id: recording_id}).done(this.renderSingleRecording) updateProgressOnSync: ($track, queue, percentage) => state = if queue == 'upload' then '.upload-state' else '.client-state' $progress = $track.find("#{state} .progress") $progress.css('width', percentage + '%') renderFinishCommand: (commandId, data) => reason = data.commandReason success = data.commandSuccess if commandId == @downloadCommandId this.logResult(@downloadMetadata, success, reason, false) recordingId = @downloadMetadata['recording_id'] this.updateSingleRecording(recordingId) if recordingId? else if commandId == @uploadCommandId this.logResult(@uploadMetadata, success, reason, false) recordingId = @uploadMetadata['recording_id'] this.updateSingleRecording(recordingId) if recordingId? else if commandId == @cleanupCommandId this.logResult(@cleanupMetadata, success, reason, false) else @logger.error("unknown commandId in renderFinishCommand") # refresh the header when done. we need to leave this callback to let the command fully switch to off #setTimeout(this.renderHeader, 1) this.renderHeader() renderPercentage: (commandId, commandType, percentage) => if commandId == @downloadCommandId $progress = @downloadProgress.find('.progress') $progress.css('width', percentage + '%') if @downloadMetadata.type == 'recorded_track' or @downloadMetadata.type == 'recorded_backing_track' clientTrackId = @downloadMetadata['track_id'] recordingId = @downloadMetadata['recording_id'] $matchingTrack = @list.find(".track-item.sync[data-recording-id='#{recordingId}'][data-client-track-id='#{clientTrackId}']") if $matchingTrack.length > 0 this.updateProgressOnSync($matchingTrack, 'download', percentage) else if commandId == @uploadCommandId $progress = @uploadProgress.find('.progress') $progress.css('width', percentage + '%') if (@uploadMetadata.type == 'recorded_track' or @uploadMetadata.type == 'recorded_backing_track') and @uploadMetadata.action == 'upload' clientTrackId = @uploadMetadata['track_id'] recordingId = @uploadMetadata['recording_id'] $matchingTrack = @list.find(".track-item.sync[data-recording-id='#{recordingId}'][data-client-track-id='#{clientTrackId}']") if $matchingTrack.length > 0 this.updateProgressOnSync($matchingTrack, 'upload', percentage) else if @uploadMetadata.type == 'stream_mix' and @uploadMetadata.action == 'upload' recordingId = @uploadMetadata['recording_id'] $matchingStreamMix = @list.find(".stream-mix.sync[data-recording-id='#{recordingId}']") if $matchingStreamMix.length > 0 this.updateProgressOnSync($matchingStreamMix, 'upload', percentage) else if commandId == @cleanupCommandId # ignore else @logger.error("unknown commandId in renderFinishCommand") fileManagerCmdStart: (e, data) => #console.log("fileManagerCmdStart", data) commandId = data['commandId'] commandType = data['commandType'] commandMetadata = data['commandMetadata'] category = commandMetadata.queue if category == 'download' && (@downloadCommandId != null && @downloadCommandId != commandId) @logger.warn("received command-start for download but previous command did not send stop") this.renderFinishCommand(commandId, category) else if @uploadCommandId != null && @uploadCommandId != commandId @logger.warn("received command-start for upload but previous command did not send stop") this.renderFinishCommand(commandId, category) this.renderStartCommand(commandId, commandType, commandMetadata) fileManagerCmdStop: (e, data) => #console.log("fileManagerCmdStop", data) commandId = data['commandId'] if commandId == @downloadCommandId this.renderFinishCommand(commandId, data) @downloadCommandId = null @downloadMetadata = null; else if commandId == @uploadCommandId this.renderFinishCommand(commandId, data) @uploadCommandId = null @uploadMetadata = null else if commandId == @cleanupCommandId this.renderFinishCommand(commandId, data) @cleanupCommandId = null @cleanupMetadata = null else @logger.warn("received command-stop for unknown command: #{commandId} #{@downloadCommandId} #{@uploadCommandId} #{@cleanupCommandId}" ) fileManagerCmdProgress: (e, data) => #console.log("fileManagerCmdProgress", data) commandId = data['commandId'] if commandId == @downloadCommandId category = 'download' this.renderPercentage(commandId, category, data.percentage) else if commandId == @uploadCommandId category = 'upload' this.renderPercentage(commandId, category, data.percentage) else if commandId == @cleanupCommandId # do nothing else @logger.warn("received command-percentage for unknown command") fileManagerAsapCommandStatus: (e, data) => this.logResult(data.commandMetadata, false, data.commandReason, true) displayName: (metadata) => if (metadata.type == 'recorded_track' || metadata.type == 'recorded_backing_track') && metadata.action == 'download' return 'DOWNLOADING TRACK' else if (metadata.type == 'recorded_track' || metadata.type == 'recorded_backing_track') && metadata.action == 'upload' return 'UPLOADING TRACK' else if metadata.type == 'mix' && metadata.action == 'download' return 'DOWNLOADING MIX' else if (metadata.type == 'recorded_track' || metadata.type == 'recorded_backing_track') && metadata.action == 'convert' return 'COMPRESSING TRACK' else if (metadata.type == 'recorded_track' || metadata.type == 'recorded_backing_track') && metadata.action == 'delete' return 'CLEANUP TRACK' else if metadata.type == 'stream_mix' && metadata.action == 'upload' return 'UPLOADING STREAM MIX' else if metadata.type == 'recording_directory' && metadata.action == 'delete' return 'DELETE RECORDING' else return "#{metadata.action} #{metadata.type}".toUpperCase() shownTab: () => @tabSelectors.filter('.selected') # create a log in the Log tab logResult: (metadata, success, reason, isAsap) => # if an error comes in, and the log tab is not already showing, increment the badge if not success and (!@showing || this.shownTab().attr('purpose') != 'log') @logBadge.css('display', 'inline-block') if @showing # don't do animation unless user can see it @logBadge.pulse({'background-color' : '#868686'}, {pulses: 2}, () => @logBadge.css('background-color', '#980006')) displayReason = switch reason when 'no-match-in-queue' then 'restart JamKazam' when 'already-done' then 'ignored, already done' when 'failed-convert' then 'failed previously' when 'minimum-protection-time' then 'too soon to delete' else reason displaySuccess = if success then 'yes' else 'no' $log = context._.template(@templateLogItem.html(), {isAsap: isAsap, command: this.displayName(metadata), success: success, displaySuccess: displaySuccess, detail: displayReason, when: new Date()}, {variable: 'data'}) @logList.prepend($log)