jam-cloud/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.c...

485 lines
16 KiB
CoffeeScript

context = window
rest = context.JK.Rest()
SessionActions = @SessionActions
MixerActions = @MixerActions
JamTrackActions = @JamTrackActions
MIX_MODES = context.JK.MIX_MODES
EVENTS = context.JK.EVENTS
ChannelGroupIds = context.JK.ChannelGroupIds
@SessionMediaTracks = React.createClass({
mixins: [@SessionMediaTracksMixin,
Reflux.listenTo(@SessionMediaTracksStore,"onInputsChanged"),
Reflux.listenTo(@AppStore,"onAppInit"),
Reflux.listenTo(@JamTrackStore, "onJamTrackStateChanged")]
onJamTrackStateChanged: (jamTrackState) ->
@setState({jamTrackState: jamTrackState})
if jamTrackState.fullTrackActivated || jamTrackState.opened && jamTrackState.jamTrack.activeMixdown == null
@loadJamTrack(jamTrackState.jamTrack)
else if jamTrackState.closed
logger.debug("SessionMediaTracks: jamtrack has been closed", jamTrackState)
if @state.downloadJamTrack?
logger.debug("closing DownloadJamTrack widget")
@state.downloadJamTrack.root.remove()
@state.downloadJamTrack.destroy()
SessionActions.downloadingJamTrack(false)
@setState({downloadJamTrack: null})
MixerActions.closeMedia.trigger(true)
#inputsChangedProcessed: (state) ->
closeWindow: () ->
if @childWindow?
@childWindow.DontAutoCloseMedia = true
@childWindow.close()
closeAudio: (e) ->
e.preventDefault()
logger.debug("SessionMediaTracks.closeAudio")
MixerActions.closeMedia(false)
cancelDownloadJamTrack: (e) ->
e.preventDefault()
logger.debug("closing DownloadJamTrack widget")
@state.downloadJamTrack.root.remove()
@state.downloadJamTrack.destroy()
SessionActions.downloadingJamTrack(false)
@setState({downloadJamTrack: null})
openRecording: (e) ->
e.preventDefault()
# just ignore the click if they are currently recording for now
if @state.isRecording
@app.notify({
"title": "Currently Recording",
"text": "You can't open a recording while creating a recording.",
"icon_url": "/assets/content/icon_alert_big.png"
})
return
@app.layout.showDialog('localRecordings') unless @app.layout.isDialogShowing('localRecordings')
# openBackingTrack: (e) ->
# e.preventDefault()
# if @state.backingTrackDialogOpen
# logger.debug("backing track dialog already open")
# return
# # just ignore the click if they are currently recording for now
# if @state.isRecording
# @app.notify({
# "title": "Currently Recording",
# "text": "You can't open a backing track while creating a recording.",
# "icon_url": "/assets/content/icon_alert_big.png"
# });
# return
# @setState({backingTrackDialogOpen: true})
# context.jamClient.ShowSelectBackingTrackDialog("window.JK.HandleBackingTrackSelectedCallback2");
openBackingTrack: `async function(e) {
e.preventDefault();
if (this.state.backingTrackDialogOpen) {
logger.debug("backing track dialog already open");
return;
}
// just ignore the click if they are currently recording for now
if (this.state.isRecording) {
this.app.notify({
"title": "Currently Recording",
"text": "You can't open a backing track while creating a recording.",
"icon_url": "/assets/content/icon_alert_big.png"
});
return;
}
this.setState({backingTrackDialogOpen: true});
await context.jamClient.ShowSelectBackingTrackDialog("window.JK.HandleBackingTrackSelectedCallback2");
}`
openMetronome: (e) ->
if @state.isRecording
@app.notify({
"title": "Currently Recording",
"text": "You can't open a metronome while creating a recording.",
"icon_url": "/assets/content/icon_alert_big.png"
})
return
SessionActions.openMetronome()
openJamTrack: (e) ->
e.preventDefault()
if @state.isRecording
@app.notify({
"title": "Currently Recording",
"text": "You can't open a jam track while creating a recording.",
"icon_url": "/assets/content/icon_alert_big.png"
})
return
@app.layout.showDialog('open-jam-track-dialog').one(EVENTS.DIALOG_CLOSED, (e, data) =>
# once the dialog is closed, see if the user has a jamtrack selected
if !data.canceled && data.result.jamTrack
JamTrackActions.open(data.result.jamTrack)
else
logger.debug("OpenJamTrack dialog closed with no selection; ignoring", data)
)
# loadJamTrack: (jamTrack) ->
# if @state.downloadJamTrack
# # if there was one showing before somehow, destroy it.
# logger.warn("destroying existing JamTrack")
# @state.downloadJamTrack.root.remove()
# @state.downloadJamTrack.destroy()
# #set to null
# downloadJamTrack = new context.JK.DownloadJamTrack(@app, jamTrack, 'large');
# # the widget indicates when it gets to any transition; we can hide it once it reaches completion
# $(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, (e, data) =>
# if data.state == downloadJamTrack.states.synchronized
# logger.debug("jamtrack synchronized; hide widget and show tracks")
# downloadJamTrack.root.remove()
# downloadJamTrack.destroy()
# downloadJamTrack = null
# this.setState({downloadJamTrack: null})
# # XXX: test with this removed; it should be unnecessary
# context.jamClient.JamTrackStopPlay();
# sampleRate = context.jamClient.GetSampleRate()
# sampleRateForFilename = if sampleRate == 48 then '48' else '44'
# fqId = jamTrack.id + '-' + sampleRateForFilename
# if jamTrack.jmep
# logger.debug("setting jmep data")
# context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep)
# else
# logger.debug("no jmep data for jamtrack")
# # JamTrackPlay means 'load'
# result = context.jamClient.JamTrackPlay(fqId);
# SessionActions.downloadingJamTrack(false)
# console.log("JamTrackPlay: result", result)
# if !result
# @app.notify(
# {
# title: "JamTrack Can Not Open",
# text: "Unable to open your JamTrack. Please contact support@jamkazam.com"
# }
# , null, true)
# else
# participantCnt = context.SessionStore.participants().length
# rest.playJamTrack(jamTrack.id)
# .done(() =>
# @app.refreshUser();
# )
# context.stats.write('web.jamtrack.open', {
# value: 1,
# session_size: participantCnt,
# user_id: context.JK.currentUserId,
# user_name: context.JK.currentUserName
# })
# )
# @setState({downloadJamTrack: downloadJamTrack})
loadJamTrack: `async function(jamTrack) {
if (this.state.downloadJamTrack) {
// if there was one showing before somehow, destroy it.
logger.warn("destroying existing JamTrack");
this.state.downloadJamTrack.root.remove();
this.state.downloadJamTrack.destroy();
}
//set to null
let downloadJamTrack = new context.JK.DownloadJamTrack(this.app, jamTrack, 'large');
// the widget indicates when it gets to any transition; we can hide it once it reaches completion
$(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, async (e, data) => {
if (data.state === downloadJamTrack.states.synchronized) {
logger.debug("jamtrack synchronized; hide widget and show tracks");
downloadJamTrack.root.remove();
downloadJamTrack.destroy();
downloadJamTrack = null;
this.setState({downloadJamTrack: null});
//XXX: test with this removed; it should be unnecessary
await context.jamClient.JamTrackStopPlay();
const sampleRate = await context.jamClient.GetSampleRate();
const sampleRateForFilename = sampleRate === 48 ? '48' : '44';
const fqId = jamTrack.id + '-' + sampleRateForFilename;
if (jamTrack.jmep) {
logger.debug("setting jmep data");
await context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep);
} else {
logger.debug("no jmep data for jamtrack");
}
// JamTrackPlay means 'load'
const result = await context.jamClient.JamTrackPlay(fqId);
SessionActions.downloadingJamTrack(false);
console.log("JamTrackPlay: result", result);
if (!result) {
return this.app.notify(
{
title: "JamTrack Can Not Open",
text: "Unable to open your JamTrack. Please contact support@jamkazam.com"
}
, null, true);
} else {
const participantCnt = context.SessionStore.participants().length;
rest.playJamTrack(jamTrack.id)
.done(() => {
return this.app.refreshUser();
});
return context.stats.write('web.jamtrack.open', {
value: 1,
session_size: participantCnt,
user_id: context.JK.currentUserId,
user_name: context.JK.currentUserName
});
}
}
});
return this.setState({downloadJamTrack});
}`
render: () ->
content = null
scrollerClassData = {'session-tracks-scroller': true}
mediaOptions = `<div className="media-options">
<div className="open-media-file-header">
<div className="vertical-helper" />
<img src="/assets/content/icon_open_folder.png" width="21" height="21" />
<span className="open-text">Open:</span>
</div>
<ul className="open-media-file-options">
<li>
<a className="open-recording" onClick={this.openRecording}>Recording</a>
</li>
<li>
<a className="open-jamtrack" onClick={this.openJamTrack}>JamTrack</a>
</li>
<li>
<a className="open-backingtrack" onClick={ this.openBackingTrack }>Audio File</a>
</li>
</ul>
<div className="use-metronome-header">
<img src="/assets/content/icon_instrument_metronome21.png" width="21" height="21" />
<a className="open-metronome" onClick={this.openMetronome}>Use Metronome</a>
</div>
</div>`
contents = null
mediaTracks = []
mediaTracks.push `<div key="download-jamtrack-holder" className="download-jamtrack-holder"></div>`
if this.state.downloadJamTrack?
closeOptions =
`<div>
<a className="closeAudio" onClick={this.cancelDownloadJamTrack}>
<img src="/assets/content/icon_close.png" width="18" height="20" />
Close JamTrack
</a>
</div>`
contents = closeOptions
else if this.state.mediaSummary.mediaOpen || @state.jamTrackState?.jamTrack?
only_opener = false
# give the users options to close it
if this.state.mediaSummary.recordingOpen
mediaType = "Recording"
only_opener = true
else if this.state.mediaSummary.jamTrackOpen || @state.jamTrackState?.jamTrack?
mediaType = "JamTrack"
only_opener = true
else if this.state.mediaSummary.backingTrackOpen
mediaType = "Audio File"
only_opener = true
else if this.state.mediaSummary.metronomeOpen
mediaType = "Metronome"
else
mediaType = ""
if !only_opener || this.state.mediaSummary.isOpener
closeOptions = `<a className="closeAudio" onClick={this.closeAudio}>
<img src="/assets/content/icon_close.png" width="18" height="20" />
Close {mediaType}
</a>`
else
if @state.popupOpen
closeOptions = `<a className="popup-open">
</a>`
else
closeOptions = `<a className="reopen-popup" href='#' onClick={this.handlePopup}>
Reopen Popup
</a>`
content = null
if this.state.mediaSummary.backingTrackOpen
for backingTrack in @state.backingTracks
backingTrack.mode = @props.mode
mediaTracks.push(`<SessionBackingTrack key={backingTrack.track.id} {...backingTrack} />`)
else if this.state.mediaSummary.recordingOpen
mediaTracks.push(`<SessionRecordedCategory key="RecordedCategory" recordingName={this.state.recordingName} mixers={this.state.mediaCategoryMixer} mode={this.props.mode} />`)
for recordedTrack in @state.recordedTracks
recordedTrack.mode = @props.mode
mediaTracks.push(`<SessionRecordedTrack key={recordedTrack.track.id} {...recordedTrack} />`)
# if a JamTrack is also open (meaning the Recording was made with a Jamtrack), show it's mixers as well
if this.state.mediaSummary.jamTrackOpen
for jamTrack in @state.jamTracks
jamTrack.mode = @props.mode
mediaTracks.push(`<SessionJamTrack key={jamTrack.id} {...jamTrack} />`)
else if this.state.mediaSummary.jamTrackOpen
# JamTrack shows in this order:
# The Category mixer
# The Metronome
# All the JamTracks
mediaTracks.push(`<SessionJamTrackCategory key="JamTrackCategory" jamTrackName={this.state.jamTrackName} mixers={this.state.mediaCategoryMixer} mode={this.props.mode} />`)
if @state.metronome? # && @state.jamTrackMixdown.id == null
@state.metronome.mode = @props.mode
mediaTracks.push(`<SessionMetronome key="JamTrackMetronome" {...this.state.metronome} location="jam-track" />`)
for jamTrack in @state.jamTracks
jamTrack.mode = @props.mode
mediaTracks.push(`<SessionJamTrack key={jamTrack.id} {...jamTrack} />`)
else if this.state.mediaSummary.metronomeOpen
@state.metronome.mode = @props.mode
mediaTracks.push(`<SessionMetronome key={this.state.metronome.id} {...this.state.metronome} />`)
contents = closeOptions
else
scrollerClassData['media-options-showing'] = true
contents = mediaOptions
scrollerClasses = classNames(scrollerClassData)
`<div className="session-media-tracks">
<h2>recorded audio <span className="session-tracks-help">?</span></h2>
{contents}
<div className={scrollerClasses}>
{content}
{mediaTracks}
</div>
</div>`
getInitialState:() ->
{mediaSummary:{mediaOpen: false}, isRecording: false, backingTracks: [], jamTracks: [], recordedTracks: [], metronome: null, jamTrackState: {}, popupOpen: false}
onAppInit: (app) ->
@app = app
$(context.AppStore).on('SessionEnded', @onSessionEnded)
onSessionEnded: () ->
@closeWindow()
handleBackingTrackSelectedCallback: (result) ->
@setState({backingTrackDialogOpen: false})
SessionActions.openBackingTrack(result)
componentDidMount: () ->
context.JK.HandleBackingTrackSelectedCallback2 = @handleBackingTrackSelectedCallback
$root = $(@getDOMNode())
context.JK.helpBubble($root.find(".session-tracks-help"), "session-media-tracks-instructions", {}, {offsetParent:$root.closest('.top-parent'), positions: ['right', 'bottom'], width:450})
componentDidUpdate: () ->
if @state.downloadJamTrack?
$holder = $(@getDOMNode()).find('.download-jamtrack-holder')
if $holder.find('.download-jamtrack').length == 0
SessionActions.downloadingJamTrack(true)
$holder.append(@state.downloadJamTrack.root)
# kick off the download JamTrack process
@state.downloadJamTrack.init()
@handlePopup()
windowUnloaded : () ->
logger.debug('SessionMediaTracks: window unloaded')
@setState({popupOpen: false})
@childWindow = null
handlePopup: () ->
if @state.mediaSummary.userNeedsMediaControls || @state.jamTrackState?.jamTrack?
unless @childWindow?
logger.debug("opening media control window")
@childWindow = window.open("/popups/media-controls", 'Media Controls', 'scrollbars=yes,toolbar=no,status=no,height=155,width=350')
console.log('childWindow', @childWindow)
@childWindow.PopupProps = {media: @state, jamTrackState: context.JamTrackStore.getState(), downloadingJamTrack: context.SessionStore.downloadingJamTrack, windowUnloaded: @windowUnloaded }
if !@state.popupOpen
setTimeout(() =>
@setState({popupOpen: true})
, 1)
else
if @childWindow?
@childWindow.DontAutoCloseMedia = true
@childWindow.close()
@childWindow = null
if @state.popupOpen
setTimeout(() =>
@setState({popupOpen: false})
, 1)
})