From bd0dc40a4c3892911545080c09af088c10b072bf Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 24 Jun 2016 09:15:04 -0500 Subject: [PATCH] initial version of jamblaster management page --- ruby/lib/jam_ruby/jam_track_importer.rb | 72 +++- ruby/lib/jam_ruby/models/jam_track.rb | 11 +- .../dialog/configureTrackDialog.js | 13 +- .../javascripts/everywhere/everywhere.js | 1 + .../javascripts/jquery.jamblasterOptions.js | 8 +- .../assets/javascripts/react-components.js | 1 + ...onfigureTracksDialogContents.js.jsx.coffee | 92 +++++ .../JamBlasterNameDialog.js.jsx.coffee | 10 +- .../JamBlasterPairingDialog.js.jsx.coffee | 60 +-- .../JamBlasterPortDialog.js.jsx.coffee | 83 +++++ .../JamBlasterScreen.js.jsx.coffee | 326 +++++++++++++++-- .../JamBlasterTrackConfig.js.jsx.coffee | 187 ++++++++++ ...essionMasterCategoryControls.js.jsx.coffee | 1 - .../SessionMasterMediaTracks.js.jsx.coffee | 1 - .../SessionMasterMyTracks.js.jsx.coffee | 1 - .../SessionMasterOtherTracks.js.jsx.coffee | 1 - .../SessionMediaTracks.js.jsx.coffee | 5 +- .../SessionMyTracks.js.jsx.coffee | 5 +- .../SessionNotifications.js.jsx.coffee | 4 +- .../SessionOtherTracks.js.jsx.coffee | 6 +- .../actions/CallbackActions.js.coffee | 6 + .../actions/JamBlasterActions.js.coffee | 10 + .../helpers/MixerHelper.js.coffee | 2 +- .../mixins/BonjourMixin.js.coffee | 90 +---- .../stores/CallbackStore.js.coffee | 24 ++ .../stores/JamBlasterStore.js.coffee | 345 ++++++++++++++++++ web/app/assets/javascripts/trackHelpers.js | 11 +- web/app/assets/javascripts/utils.js | 9 + .../stylesheets/client/content.css.scss | 2 +- .../client/jamblasterOptions.css.scss | 4 + .../JamBlasterScreen.css.scss | 154 +++++++- .../JamBlasterTrackConfig.css.scss | 80 ++++ .../dialogs/configureTracksDialog.css.scss | 4 +- .../dialogs/jamblasterNameDialog.css.scss | 5 +- .../dialogs/jamblasterPairingDialog.css.scss | 17 +- .../dialogs/jamblasterPortDialog.css.scss | 43 +++ .../clients/_jamblasterOptions.html.slim | 11 +- .../_clientPreferencesDialog.html.slim | 2 +- .../_configure_tracks_dialog.html.haml | 49 +-- web/app/views/dialogs/_dialogs.html.haml | 1 + .../dialogs/_jamblasterPortDialog.html.slim | 2 + web/app/views/users/_user_dropdown.html.erb | 3 + web/lib/tasks/jam_tracks.rake | 11 +- 43 files changed, 1512 insertions(+), 261 deletions(-) create mode 100644 web/app/assets/javascripts/react-components/ConfigureTracksDialogContents.js.jsx.coffee create mode 100644 web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee create mode 100644 web/app/assets/javascripts/react-components/JamBlasterTrackConfig.js.jsx.coffee create mode 100644 web/app/assets/javascripts/react-components/actions/CallbackActions.js.coffee create mode 100644 web/app/assets/javascripts/react-components/actions/JamBlasterActions.js.coffee create mode 100644 web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee create mode 100644 web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee create mode 100644 web/app/assets/stylesheets/client/react-components/JamBlasterTrackConfig.css.scss create mode 100644 web/app/assets/stylesheets/dialogs/jamblasterPortDialog.css.scss create mode 100644 web/app/views/dialogs/_jamblasterPortDialog.html.slim diff --git a/ruby/lib/jam_ruby/jam_track_importer.rb b/ruby/lib/jam_ruby/jam_track_importer.rb index 31e049d96..21ce287c4 100644 --- a/ruby/lib/jam_ruby/jam_track_importer.rb +++ b/ruby/lib/jam_ruby/jam_track_importer.rb @@ -66,8 +66,8 @@ module JamRuby return end - #wav_file = File.join(tmp_dir, File.basename(click_track_file[:original_filename])) - #JamTrackImporter.song_storage_manager.download(click_track_file[:original_filename], wav_file) + wav_file = File.join(tmp_dir, File.basename(click_track_file[:original_filename])) + JamTrackImporter.song_storage_manager.download(click_track_file[:original_filename], wav_file) JamTrack.transaction do click_track = jam_track.click_track @@ -81,6 +81,8 @@ module JamRuby click_track.instrument_id = 'computer' click_track.jam_track = jam_track click_track.position = 10000 + click_track.wav_file = wav_file + if !click_track.save @@log.error("unable to create jamtrack click track #{click_track.errors.inspect}") finish("jam_track_click", "unable to create: #{click_track.errors.inspect}") @@ -1601,6 +1603,8 @@ module JamRuby end end + + def assign_instrument_parts(wav_file, tracks, addt_files, reassign = false) if !reassign track = JamTrackTrack.new @@ -2651,6 +2655,34 @@ module JamRuby importer end + # created for helbing tracks which had .mp3 as click track + def convert_click_track_to_wav(jam_track) + importer = JamTrackImporter.new + importer.name = jam_track.name + + track = jam_track.click_track + + if !track + Dir.mktmpdir do |tmp_dir| + + # something like: "mapped/Victor Young - Stella By Starlight/meta.yml" + metalocation = jam_track.metalocation + base_dir = metalocation[0...metalocation.rindex('/')] + click_mp3 = File.join(tmp_dir, 'Click.mp3') + click_wav = File.join(tmp_dir, 'Click.wav') + song_storage_manager.download(base_dir + '/Click.mp3', click_mp3) + + `ffmpeg -i "#{click_mp3}" "#{click_wav}"` + + song_storage_manager.upload(base_dir + '/Click.wav', click_wav) + importer.finish("success", nil) + end + else + importer.finish('success', nil) + end + importer + end + def synchronize_jamtrack_master_preview(jam_track) importer = JamTrackImporter.new importer.name = jam_track.name @@ -2717,7 +2749,8 @@ module JamRuby def import_click_tracks importers = [] - JamTrack.all.each do |jam_track| + licensor = JamTrackLicensor.find_by_name!('Stockton Helbing') + JamTrack.where(licensor_id: licensor.id).each do |jam_track| #jam_track = JamTrack.find('126') importers << import_click_track(jam_track) end @@ -2796,6 +2829,32 @@ module JamRuby end end + def convert_click_track_to_wavs + importers = [] + + licensor = JamTrackLicensor.find_by_name!('Stockton Helbing') + JamTrack.where(licensor_id: licensor.id).each do |jam_track| + importers << convert_click_track_to_wav(jam_track) + end + + @@log.info("SUMMARY") + @@log.info("-------") + importers.each do |importer| + if importer + if importer.reason == "success" || importer.reason == "jam_track_exists" || importer.reason == "other_processing" + @@log.info("#{importer.name} #{importer.reason}") + else + @@log.error("#{importer.name} failed to import.") + @@log.error("#{importer.name} reason=#{importer.reason}") + @@log.error("#{importer.name} detail=#{importer.detail}") + end + else + @@log.error("NULL IMPORTER") + end + + + end + end def synchronize_jamtrack_aac_previews importers = [] @@ -2818,8 +2877,6 @@ module JamRuby else @@log.error("NULL IMPORTER") end - - end end @@ -3118,11 +3175,11 @@ module JamRuby def resync_instruments(licensor) - load_paris_mappings if @paris_mapping.nil? + load_paris_mappings if @paris_mapping.nil? && is_paris_storage? JamTrack.where(licensor_id: licensor.id).each do |jam_track| - if @paris_metadata[jam_track.vendor_id].nil? + if is_paris_storage? && @paris_metadata[jam_track.vendor_id].nil? next end puts "RESYNCING JAMTRACK #{jam_track.id}" @@ -3135,6 +3192,7 @@ module JamRuby #puts ">>>>>>>>> HIT KEY TO CONTINUE <<<<<<<<<<" #STDIN.gets + break end end diff --git a/ruby/lib/jam_ruby/models/jam_track.rb b/ruby/lib/jam_ruby/models/jam_track.rb index 72febb08c..0c6aeb1f9 100644 --- a/ruby/lib/jam_ruby/models/jam_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track.rb @@ -323,7 +323,16 @@ module JamRuby end if options[:artist].present? - query = query.where("original_artist=?", options[:artist]) + artist_param = options[:artist] + # todo: add licensor option + if artist_param == 'Stockton Helbing' + licensor = JamTrackLicensor.find_by_name('Stockton Helbing') + if licensor + query = query.where(licensor_id: licensor.id) + end + else + query = query.where("original_artist=?", options[:artist]) + end end if options[:song].present? diff --git a/web/app/assets/javascripts/dialog/configureTrackDialog.js b/web/app/assets/javascripts/dialog/configureTrackDialog.js index ccdee9b1f..c7b908fbc 100644 --- a/web/app/assets/javascripts/dialog/configureTrackDialog.js +++ b/web/app/assets/javascripts/dialog/configureTrackDialog.js @@ -128,10 +128,11 @@ return false; }); - //$btnAddNewGear.click(function() { + $btnAddNewGear.click(function() { - // return false; - //}); + app.layout.showDialog("add-new-audio-gear") + return false; + }); $btnUpdateTrackSettings.click(function() { if(voiceChatHelper.trySave()) { @@ -245,6 +246,8 @@ function afterShow() { sessionUtils.SessionPageEnter(); + window.JamBlasterActions.resyncBonjour() + //context.ConfigureTracksActions.vstScan(); } @@ -271,9 +274,9 @@ $dialog = $('#configure-tracks-dialog'); $instructions = $dialog.find('.instructions span'); - $musicAudioTab = $dialog.find('div[tab-id="music-audio"]'); + $musicAudioTab = $dialog.find('div[data-tab-id="music-audio"]'); $musicAudioTabSelector = $dialog.find('.tab-configure-audio'); - $voiceChatTab = $dialog.find('div[tab-id="voice-chat"]'); + $voiceChatTab = $dialog.find('div[data-tab-id="voice-chat"]'); $voiceChatTabSelector = $dialog.find('.tab-configure-voice'); $certifiedAudioProfile = $dialog.find('.certified-audio-profile'); $btnCancel = $dialog.find('.btn-cancel'); diff --git a/web/app/assets/javascripts/everywhere/everywhere.js b/web/app/assets/javascripts/everywhere/everywhere.js index 29eba67cd..82ce6acda 100644 --- a/web/app/assets/javascripts/everywhere/everywhere.js +++ b/web/app/assets/javascripts/everywhere/everywhere.js @@ -210,6 +210,7 @@ JK.JamServer.registerMessageCallback(JK.MessageType.STOP_APPLICATION, function(header, payload) { context.jamClient.ShutdownApplication(); }); + } function handleGettingStarted(app) { diff --git a/web/app/assets/javascripts/jquery.jamblasterOptions.js b/web/app/assets/javascripts/jquery.jamblasterOptions.js index 9f947359e..43ad64b5c 100644 --- a/web/app/assets/javascripts/jquery.jamblasterOptions.js +++ b/web/app/assets/javascripts/jquery.jamblasterOptions.js @@ -49,9 +49,15 @@ var html = context._.template($('#template-jamblaster-options').html(), options, { variable: 'data' }) + var extraClasses = ' ' + var width = 120; + if(options.isDynamicPorts || options.autoconnect) { + extraClasses += 'isDynamicPorts ' + width = 140; + } context.JK.hoverBubble($parent, html, { trigger:'none', - cssClass: 'jamblaster-options-popup', + cssClass: 'jamblaster-options-popup' + extraClasses, spikeGirth:0, spikeLength:0, overlap: -10, diff --git a/web/app/assets/javascripts/react-components.js b/web/app/assets/javascripts/react-components.js index c08afc511..10a21bb99 100644 --- a/web/app/assets/javascripts/react-components.js +++ b/web/app/assets/javascripts/react-components.js @@ -8,6 +8,7 @@ //= require ./react-components/stores/UserActivityStore //= require ./react-components/stores/LessonTimerStore //= require ./react-components/stores/SchoolStore +//= require ./react-components/stores/JamBlasterStore //= require ./react-components/stores/StripeStore //= require ./react-components/stores/AvatarStore //= require ./react-components/stores/AttachmentStore diff --git a/web/app/assets/javascripts/react-components/ConfigureTracksDialogContents.js.jsx.coffee b/web/app/assets/javascripts/react-components/ConfigureTracksDialogContents.js.jsx.coffee new file mode 100644 index 000000000..b9469858e --- /dev/null +++ b/web/app/assets/javascripts/react-components/ConfigureTracksDialogContents.js.jsx.coffee @@ -0,0 +1,92 @@ +context = window +JamBlasterActions = @JamBlasterActions + +@ConfigureTracksDialogContents = React.createClass({ + + mixins: [Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@JamBlasterStore, "onJamBlasterChanged")] + + + onAppInit: (@app) -> + + onJamBlasterChanged: (jamblasterState) -> + @setState(jamblasterState) + + getInitialState: () -> + { + timer: null, + pairing: false, + pairStart: null, + allJamBlasters: [], + pairingTimeout: false, + paired: false, + userJamBlasters: [], + localJamBlasters: [] + } + + + render: () -> + pairedJamBlaster = this.state.pairedJamBlaster + hasPairedJamBlaster = pairedJamBlaster? + + if hasPairedJamBlaster + `` + else + `
+
+ Inputs & Outputs + Voice Chat +
+
+ Choose your audio device. Drag and drop to assign input ports to tracks, and specify the instrument + for each track. Drag and drop to assign a pair of output ports for session stereo audio monitoring. +
+
+
+ + +
+
+
+
+
Select Voice Chat Option
+
+ + +

Use Music Microphone

+ +

I am already using a microphone to capture my vocal or instrumental music, so I can talk with other + musicians using that microphone

+
+
+ + +

Use Chat Microphone

+ +

I am not using a microphone for acoustic instruments or vocals, so use the input selected to the right + for voice chat during my sessions

+
+
+
+
+
Voice Chat Input
+
+
+
+
+
+
GAIN
+
+
+
+
+
+
+ +
+ ADD NEW AUDIO GEAR + CANCEL + SAVE SETTINGS +
+
` + } +) diff --git a/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee index 33d68f43e..1b3e77ad7 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee @@ -44,7 +44,7 @@ context = window name = @root.find('.name').val() - characterMatch = /^[a-z0-9,' -]+$/i + characterMatch = /^[^a-z0-9,' -]+$/i if name.length == 0 || name == '' context.JK.Banner.showAlert('invalid name', 'Please specify a name.') @@ -64,7 +64,7 @@ context = window if !result context.JK.Banner.showAlert('unable to set the name', - 'Please email support@jamkazam.com with the name you are trying to set, or refresh the page and try again.') + 'Please email support@jamkazam.com and let us know the name you are specifying unsuccessfully, or refresh the page and try again.') else @app.layout.closeDialog('jamblaster-name-dialog') render: () -> @@ -74,13 +74,15 @@ context = window

update name of JamBlaster

-
+
-

You can change the display name for this JamBlaster. The name can only contain A-Z, 0-9, commas, apostrophes, +

You can change the display name for this JamBlaster. The name can only contain A-Z, 0-9, commas, apostrophes, spaces, or hyphens. A valid example: "John Doe's JamBlaster"

+
+
CANCEL diff --git a/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee index 70b14ec44..3698fd26e 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee @@ -1,13 +1,15 @@ context = window +JamBlasterActions = @JamBlasterActions + @JamBlasterPairingDialog = React.createClass({ - mixins: [@BonjourMixin, Reflux.listenTo(@AppStore, "onAppInit")] - teacher: null + mixins: [@BonjourMixin, Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@JamBlasterStore, "onJamBlasterChanged")] + beforeShow: (args) -> logger.debug("JamBlasterPairingDialog.beforeShow", args.d1) @setState({timer: null, pairing: false, bonjourClientId: args.d1, pairingTimeout: false, paired: false}) - @resyncBonjour() + JamBlasterActions.resyncBonjour() @setTimer(false) afterHide: () -> @@ -21,16 +23,19 @@ context = window @app.bindDialog('jamblaster-pairing-dialog', dialogBindings); + onJamBlasterChanged: (jamblasterState) -> + @setState(jamblasterState) + getInitialState: () -> { - timer: null + timer: null, pairing: false, pairStart: null, - clients: [], - pairingTimeout: false + allJamBlasters: [], + pairingTimeout: false, paired: false, userJamBlasters: [], - localClients: [] + localJamBlasters: [] } clearTimer: () -> @@ -51,7 +56,7 @@ context = window else time = 60000 # every minute - @interval = setInterval((() => @resyncBonjour()), time) + @interval = setInterval((() => JamBlasterActions.resyncBonjour()), time) pairingTimer: () -> @clearPairingTimer() @@ -101,7 +106,7 @@ context = window if @state.pairing return - @setState({pairing: true, pairStart: new Date().getTime(), timer: 60}) + @setState({pairing: true, pairStart: new Date().getTime(), timer: 60, pairingTimeout: false, paired: false}) @setTimer(true) client = @findJamBlaster(this.state.bonjourClientId) @@ -110,52 +115,55 @@ context = window context.JK.Banner.showNotice("JamBlaster already paired", "This JamBlaster is already paired.") @app.layout.closeDialog("jamblaster-pairing-dialog", true) else if client? - if client.connect_url? - context.jamClient.startPairing(client.connect_url) - else - context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it") + logger.debug("trying to connect to #{client.connect_url}") + if client.connect_url? + @pairingTimer() + context.jamClient.startPairing(client.connect_url) else - context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it") + context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it.") + else + context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it.") render: () -> if @state.pairing - countdown = @state.timer + countdown = `
You have {Math.round(this.state.timer)} seconds to push the button on the back of the JamBlaster. +
` else countdown = null + + cancelClasses = {"button-grey": true, disabled: @state.pairing} + connectClasses = {"button-orange": true, disabled: @state.pairing} + actions = `
- CANCEL - CONNECT - {countdown} + CANCEL + CONNECT
` if @state.paired - message = `

You have successfully connected to this JamBlaster!

` + message = `

You have successfully connected to this JamBlaster!

` actions = `` else if @state.pairingTimeout - message = `

No connection established. You may click the CONNECT button to try again. If you cannot connect, please contact us at support@jamkazam.com.

` + message = `

No connection established. You may click the CONNECT button to try again. If you cannot connect, please contact us at support@jamkazam.com.

` else - cancelClasses = {"button-grey": true, disabled: @state.pairing} - connectClasses = {"button-orange": true, disabled: @state.pairing} - `

connect to JamBlaster

-
+
-

To connect this application/device with the selected JamBlaster, please click the Connect button below, and then push the small black plastic button located on the back of the JamBlaster between the USB and power ports to confirm this pairing within 60 seconds of clicking the Connect button below.

+

To connect this application/device with the selected JamBlaster, please click the CONNECT button below, and then push the small black plastic button located on the back of the JamBlaster between the USB and power ports to confirm this pairing within 60 seconds of clicking the Connect button below.

{message} - {actions} + {countdown} {actions}
` diff --git a/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee new file mode 100644 index 000000000..21a345a1d --- /dev/null +++ b/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee @@ -0,0 +1,83 @@ +context = window +@JamBlasterPortDialog = React.createClass({ + + mixins: [Reflux.listenTo(@AppStore, "onAppInit")] + teacher: null + + beforeShow: (args) -> + logger.debug("JamBlasterPortDialog.beforeShow") + + + afterHide: () -> + + onAppInit: (@app) -> + dialogBindings = { + 'beforeShow': @beforeShow, + 'afterHide': @afterHide + }; + + @app.bindDialog('jamblaster-port-dialog', dialogBindings); + + getInitialState: () -> + { + name: '' + } + + + componentDidMount: () -> + @root = $(@getDOMNode()) + @dialog = @root.closest('.dialog') + + doCancel: (e) -> + e.preventDefault() + @app.layout.closeDialog('jamblaster-port-dialog', true); + + updatePort: (e) -> + e.preventDefault() + + # validate + + staticPort = @root.find('.port').val() + + staticPort = new Number(staticPort); + + console.log("staticPort", staticPort) + if context._.isNaN(staticPort) + @app.layout.notify({title: 'No Settings Have Been Saved!', text: 'Please enter a number from 1026-49150.'}) + return + + if staticPort < 1026 || staticPort >= 65525 + @app.layout.notify({title: 'No Settings Have Been Saved!', text: 'Please pick a port from 1026 to 65524.'}) + return + + result = context.jamClient.setJbPortBindState({use_static_port: true, static_port: staticPort}) + + if !result + context.JK.Banner.showAlert('unable to set a static port', + 'Please email support@jamkazam.com and let us know the port number you are specifying unsuccessfully, or refresh the page and try again.') + else + @app.layout.closeDialog('jamblaster-port-dialog') + render: () -> + `
+
+ + +

set static port for JamBlaster

+
+
+ +

You can specify any port you like, but we recommend an even number in the range including 1026-49150 to avoid conflicts with other programs. When configuring Port Forwarding in your router, be sure to open this port along with the next 10. For example, if this field is 12000, then in your router, forward ports 12000-12010 to your computer's IP address.

+ +
+ + +
+ +
+ CANCEL + SAVE +
+
+
` + +}) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee index 45c8e1ba2..c2e74dac5 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee @@ -1,6 +1,7 @@ context = window rest = context.JK.Rest() logger = context.JK.logger +JamBlasterActions = @JamBlasterActions @JamBlasterScreen = React.createClass({ @@ -9,7 +10,8 @@ logger = context.JK.logger @PostProcessorMixin, @BonjourMixin, Reflux.listenTo(AppStore, "onAppInit"), - Reflux.listenTo(UserStore, "onUserChanged") + Reflux.listenTo(UserStore, "onUserChanged"), + Reflux.listenTo(JamBlasterStore, "onJamBlasterChanged") ] TILE_AUDIO: 'audio' @@ -17,7 +19,10 @@ logger = context.JK.logger TILE_MANAGEMENT: 'management' TILE_USB: 'usb' - TILES: ['audio', 'internet', 'management', 'usb'] + TILES: ['management', 'audio', 'internet'] + + networkStale: false + ipRegex: /^0([0-9])+/ onAppInit: (@app) -> @app.bindScreen('jamblaster', @@ -26,44 +31,120 @@ logger = context.JK.logger onUserChanged: (userState) -> @setState({user: userState?.user}) - componentDidMount: () -> - @root = $(@getDOMNode()) + onJamBlasterChanged: (jamblasterState) -> + @setState(jamblasterState) + + componentDidMount: () -> + @checkboxes = [{selector: 'input.dhcp', stateKey: 'dhcp'}] + @root = $(@getDOMNode()) + @iCheckify() + - componentWillUpdate: (nextProps, nextState) -> componentDidUpdate: () -> + @iCheckify() + items = @root.find('.jamtable .optionsColumn .jamblaster-options-btn') $.each(items, (i, node) => ( $node = $(node) - jamblaster = @findJamBlaster($node.attr('data-jamblaster-id')) + jamblaster = @findJamBlaster({ + server_id: $node.attr('data-jamblaster-id'), + ipv6_addr: $node.attr('data-jamblaster-addr') + }) $node.jamblasterOptions(jamblaster).off(context.JK.EVENTS.JAMBLASTER_ACTION).on(context.JK.EVENTS.JAMBLASTER_ACTION, @jamblasterOptionSelected) )) + + @root.find('input.networksettings').inputmask({ + alias: "ip", + "placeholder": "_" + }); + + checkboxChanged: (e) -> + checked = $(e.target).is(':checked') + + value = $(e.target).val() + console.log("checkbox changed: ", value) + + + @setState({userdhcp: "true" == value}) + + componentWillUpdate: (nextProps, nextState) -> + if @networkStale && @state.pairedJamBlaster? + console.log("stale network update", @state) + nextState.userdhcp = @state.pairedJamBlaster.network?.dhcp + nextState.useraddr = @state.pairedJamBlaster.network?.addr + nextState.usersubnet = @state.pairedJamBlaster.network?.subnet + nextState.usergateway = @state.pairedJamBlaster.network?.gateway + nextState.userdns1 = @state.pairedJamBlaster.network?.dns1 + nextState.userdns2 = @state.pairedJamBlaster.network?.dns2 + nextState.userdhcperror = false + nextState.useraddrerror = false + nextState.usersubneterror = false + nextState.usergatewayerror = false + nextState.userdns1error = false + nextState.userdns2error = false + @networkStale = false + #context.JK.popExternalLinks(@root) jamblasterOptionSelected: (e, data) -> - jamblasterId = data.options.id - jamblaster = @findJamBlaster(jamblasterId) + jamblaster = data.options + jamblaster = @findJamBlaster(jamblaster) if data.option == 'auto-connect' - context.JK.Banner.showNotice('Auto-Connect', - 'Auto-Connect is always on by default. It can not currently configurable.') + JamBlasterActions.setAutoPair(!jamblaster.autoconnect) else if data.option == 'restart' - context.JK.Banner.showNotice('Restart', - 'To restart the JamBlaster, you must manually cycle power (unplug, then plug).') + context.JK.Banner.showYesNo({ + title: "reboot JamBlaster", + html: "Are you sure?" + yes: => + result = context.jamClient.rebootJamBlaster() + if result + setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting", + "It should be back online within a minute.")), 1) + setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + + else + setTimeout((() => context.JK.Banner.showAlert("could not reboot", + "The JamBlaster could not be rebooted remotely. Please cycle the power manually.")), 1) + + }) + else if data.option == 'name' - context.layout.showDialog('jamblaster-name-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => - @resyncBonjour() + @app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED, + (e, data) => + setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) ) else if data.option == 'check-for-updates' context.JK.Banner.showNotice('Check for Update', - 'The JamBlaster only checks for updates on start up. Please reboot the JamBlaster') + 'The JamBlaster only checks for updates when booting up. Please reboot the JamBlaster to initiate an update check.') else if data.option == 'set-static-ports' - context.layout.showDialog('jamblaster-port-dialog') + if jamblaster.isDynamicPorts + context.JK.Banner.showYesNo({ + title: "revert to dynamic ports", + html: "Your JamBlaster is currently configured to use ports #{jamblaster.portState.static_port} - #{jamblaster.portState.static_port + 10}). Would you like to revert to the use of dynamic ports for UDP communication?" + yes: => + context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000}) + JamBlasterActions.clearPortBindState() + #setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + JamBlasterActions.resyncBonjour() + setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster", + "For these settings to take effect, you must restart the JamBlaster.")), 1) + + }) + + else + @app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => + JamBlasterActions.clearPortBindState() + JamBlasterActions.resyncBonjour() + context.JK.Banner.showNotice("reboot JamBlaster", + "For these settings to take effect, you must restart the JamBlaster.") + ) else if data.option == 'factory-reset' context.JK.Banner.showNotice('Factory Reset', 'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.

Please reboot the JamBlaster to initiate an update check.') @@ -74,17 +155,18 @@ logger = context.JK.logger selected: 'management', user: null, userJamBlasters: [], - localClients: [], - clients: [] + localJamBlasters: [], + allJamBlasters: [] } beforeHide: (e) -> - + @clearTimer() beforeShow: (e) -> + @setTimer() afterShow: (e) -> - @resyncBonjour() + JamBlasterActions.resyncBonjour() openMenu: (client, e) -> logger.debug("open jamblaster options menu") @@ -93,18 +175,34 @@ logger = context.JK.logger $this = $this.closest('.jamblaster-options-btn') $this.btOn() + clearTimer: () -> + if @interval? + clearInterval(@interval) + @interval = null + +# Refresh bonjour status every 30 second, so that we catch major changes + setTimer: () -> + @clearTimer() + time = 30000 # every 30 seconds + + @interval = setInterval((() => JamBlasterActions.resyncBonjour()), time) + connect: (client, e) -> logger.debug("beginning pairing to #{client.connect_url}") - context.jamClient.startPairing(client.connect_url) - + @clearTimer() + @app.layout.showDialog('jamblaster-pairing-dialog', {d1: client}).one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => + JamBlasterActions.resyncBonjour() + @setTimer() + ) disconnect: (client, e) -> logger.debug("disconnecting from currently paired client #{client.connect_url}") context.jamClient.endPairing() - mergeClients: () -> + setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + mergeClients: () -> clientsJsx = [] - for client in @state.clients + for client in @state.allJamBlasters if client.display_name? displayName = client.display_name else @@ -122,7 +220,9 @@ logger = context.JK.logger else connect = `offline` - options = `more options
` @@ -134,6 +234,10 @@ logger = context.JK.logger clientsJsx mainContent: () -> + if !@state.user?.id || !@state.userJamBlasters? || !@state.localJamBlasters? + return `
Loading ...
` + + if @state.selected == @TILE_AUDIO @audio() else if @state.selected == @TILE_INTERNET @@ -143,9 +247,141 @@ logger = context.JK.logger else if @state.selected == @TILE_USB @usb() + audio: () -> + `
+ +
` + + ipSettingsChanged: (key, e) -> + userKey = 'user' + key + state = {} + ip = $(e.target).val() + state[userKey] = ip + if ip? + bits = ip.split('.') + + console.log("bits", bits) + for bit in bits + result = @ipRegex.test(bit.replace(/_/g, '')) + console.log("STILL GOT THAT _?", result) + error = false + if result == true || bit == "___" + error = true + break + + if error + console.log("SETTING ERROR for " + userKey + 'error') + state[userKey + 'error'] = true + else + state[userKey + 'error'] = false + this.setState(state) + + onSaveNetworkSettings: (e) -> + e.preventDefault() + + JamBlasterActions.saveNetworkSettings({ + dhcp: this.state.userdhcp, + addr: this.state.useraddr, + gateway: this.state.usergateway, + subnet: this.state.usersubnet, + dns1: this.state.userdns1, + dns2: this.state.userdns2 + }) + @networkStale = true + + usb: () -> + `
+

USB Settings

+
` + + internet: () -> + pairedJamBlaster = this.state.pairedJamBlaster + hasPairedJamBlaster = pairedJamBlaster? + isJamBlasterDhcp = !!this.state.userdhcp + + if hasPairedJamBlaster + status = + `
+
Ethernet:Connected
+
Internet:Connected
+
Streaming:Supported
+
` + else + status = + `
+
Ethernet:Unknown
+
Internet:Unknown
+
Streaming:Unknown
+
` + + addrClasses = {field: true, error: this.state.useraddrerror} + subnetClasses = {field: true, error: this.state.usersubneterror} + gatewayClasses = {field: true, error: this.state.usergatewayerror} + dns1Classes = {field: true, error: this.state.userdns1error} + dns2Classes = {field: true, error: this.state.userdns2error} + + saveBtnClasses = {} + saveBtnClasses["save-settings-btn"] = true + saveBtnClasses["button-orange"] = true + saveBtnClasses["disabled"] = !hasPairedJamBlaster + + ipdisabled = !hasPairedJamBlaster || isJamBlasterDhcp + + `
+

Internet Settings

+ +
+
+

Assign IP Address

+ +
+ +
+
+ +
+
+
+

Manual Settings

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+

Network Status

+ {status} +
+
` + management: () -> clients = @mergeClients() + if @state.refreshingBonjour + refreshingText = 'SCANNING' + else + refreshingText = 'SCAN NETWORK' + + refreshClasses = {"resync-bonjour": true, "button-orange": true, disabled: @state.refreshingBonjour} `
+ @@ -156,23 +392,53 @@ logger = context.JK.logger {clients}
-

If you don't see your JamBlaster listed above, please check to make sure you have power connected to your JamBlaster, - and make sure your JamBlaster is connected via an Ethernet cable to the same router/network as the device on which you are viewing this application. + {refreshingText} + +

If you don't see your JamBlaster listed above, please check to make sure you have power + connected to your JamBlaster, + and make sure your JamBlaster is connected via an Ethernet cable to the same router/network as the device on + which you are viewing this application.

` + tiles: () -> + @TILES + + selectionMade: (selection, e) -> + e.preventDefault() + + if selection == @TILE_INTERNET + @networkStale = true + + @setState({selected: selection}) + + createTileLink: (i, tile) -> + if this.state.selected? + active = this.state.selected == tile + else + active = tile == @TILE_MANAGEMENT + + tileClasses = {activeTile: active, 'jamblaster-tile': true} + tileClasses = classNames(tileClasses) + + classes = classNames({last: i == @tiles().length - 1}) + + return `` + render: () -> disabled = @state.updating - if !@state.user?.id || !@state.userJamBlasters? || !@state.localClients? - return `
Loading
` - + tiles = [] + for tile, i in @tiles() + tiles.push(@createTileLink(i, tile)) `

jamblaster settings

+ {tiles}
diff --git a/web/app/assets/javascripts/react-components/JamBlasterTrackConfig.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterTrackConfig.js.jsx.coffee new file mode 100644 index 000000000..ac48f5ba0 --- /dev/null +++ b/web/app/assets/javascripts/react-components/JamBlasterTrackConfig.js.jsx.coffee @@ -0,0 +1,187 @@ +context = window +JamBlasterActions = @JamBlasterActions + +@JamBlasterTrackConfig = React.createClass({ + + mixins: [@ICheckMixin, @BonjourMixin, Reflux.listenTo(@AppStore, "onAppInit"), + Reflux.listenTo(@JamBlasterStore, "onJamBlasterChanged")] + + beforeShow: () -> + + onAppInit: (@app) -> + + onJamBlasterChanged: (jamblasterState) -> + @setState(jamblasterState) + + + componentDidMount: () -> + @checkboxes = [ + {selector: 'input.track1Active', stateKey: 'track1Active'}, + {selector: 'input.track2Active', stateKey: 'track2Active'}, + {selector: 'input.micActive', stateKey: 'micActive'}, + {selector: 'input.track1Phantom', stateKey: 'track1Phantom'}, + {selector: 'input.track2Phantom', stateKey: 'track2Phantom'}, + {selector: 'input.inputTypeTrack1', stateKey: 'inputTypeTrack1'}, + {selector: 'input.inputTypeTrack2', stateKey: 'inputTypeTrack2'}, + {selector: 'input.combined', stateKey: 'combined'}] + + @root = $(@getDOMNode()) + @iCheckify() + + + componentDidUpdate: () -> + @iCheckify() + + checkboxChanged: (e) -> + checked = $(e.target).is(':checked') + + value = $(e.target).val() + name = $(e.target).attr('name') + console.log("checkbox changed: ", value) + + if $(e.target).attr('type') == 'checkbox' + state = {} + state[name] = checked + @setState(state) + + JamBlasterActions.updateAudio(name, checked) + else + state = {} + value = value == 'line' + state[name] = value + @setState(state) + + JamBlasterActions.updateAudio(name, value) + + + getInitialState: () -> + { + allJamBlasters: [], + userJamBlasters: [], + localJamBlasters: [] + } + + convertToClientInstrument: (instrumentId) -> + clientInstrumentId = null + if instrumentId != null && instrumentId != '' + clientInstrumentId = context.JK.instrument_id_to_instrument[instrumentId].client_id + else + clientInstrumentId = 10 + clientInstrumentId + + render: () -> + pairedJamBlaster = this.state.pairedJamBlaster + hasPairedJamBlaster = pairedJamBlaster? + masterDisabled = this.props.disabled + + if !hasPairedJamBlaster + return `
+ You have no paired JamBlaster currently. If you've paired the JamBlaster in the past, be sure it's plugged in + and connected to an ethernet cable. If you have not paired a JamBlaster before, please go to the JamBlaster management page. +
` + + instruments = [] + for instrument in context.JK.server_to_client_instrument_alpha + instruments.push(``) + + combined = pairedJamBlaster.tracks?.combined + track1Active = pairedJamBlaster.tracks?.track1Active + track2Active = pairedJamBlaster.tracks?.track2Active + inputTypeTrack1 = pairedJamBlaster.tracks?.inputTypeTrack1 + inputTypeTrack2 = pairedJamBlaster.tracks?.inputTypeTrack2 + track1Phantom = pairedJamBlaster.tracks?.track1Phantom + track2Phantom = pairedJamBlaster.tracks?.track2Phantom + micActive = pairedJamBlaster.tracks?.micActive + track1Instrument = context.JK.convertClientInstrumentToServer(pairedJamBlaster.tracks?.track1Instrument) + track2Instrument = context.JK.convertClientInstrumentToServer(pairedJamBlaster.tracks?.track2Instrument) + + `
+
+

Input 1

+
+ +
+ +
+

Type

+ +
+
+ +
+
+ +
+
+
+ +
+

Power

+ +
+ +
+
+
+

Instrument

+ +
+
+
+

Input 2

+
+ +
+ +
+

Type

+ +
+
+ +
+
+ +
+
+
+ +
+

Power

+ +
+ +
+
+
+

Instrument

+ +
+
+
+

Mic

+
+ +
+
+
+ +
+ +
+
` +}) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/SessionMasterCategoryControls.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMasterCategoryControls.js.jsx.coffee index 80dd34036..087a1fd6d 100644 --- a/web/app/assets/javascripts/react-components/SessionMasterCategoryControls.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMasterCategoryControls.js.jsx.coffee @@ -1,6 +1,5 @@ context = window rest = context.JK.Rest() -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup MIX_MODES = context.JK.MIX_MODES @SessionMasterCategoryControls = React.createClass({ diff --git a/web/app/assets/javascripts/react-components/SessionMasterMediaTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMasterMediaTracks.js.jsx.coffee index 3dbf9f5b2..f65fde6cf 100644 --- a/web/app/assets/javascripts/react-components/SessionMasterMediaTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMasterMediaTracks.js.jsx.coffee @@ -1,7 +1,6 @@ context = window rest = context.JK.Rest() SessionActions = @SessionActions -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup MIX_MODES = context.JK.MIX_MODES EVENTS = context.JK.EVENTS ChannelGroupIds = context.JK.ChannelGroupIds diff --git a/web/app/assets/javascripts/react-components/SessionMasterMyTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMasterMyTracks.js.jsx.coffee index 44f879eed..5fdde3e90 100644 --- a/web/app/assets/javascripts/react-components/SessionMasterMyTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMasterMyTracks.js.jsx.coffee @@ -1,5 +1,4 @@ context = window -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup MIX_MODES = context.JK.MIX_MODES logger = context.JK.logger diff --git a/web/app/assets/javascripts/react-components/SessionMasterOtherTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMasterOtherTracks.js.jsx.coffee index d0a6626b2..598415295 100644 --- a/web/app/assets/javascripts/react-components/SessionMasterOtherTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMasterOtherTracks.js.jsx.coffee @@ -1,5 +1,4 @@ context = window -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup @SessionMasterOtherTracks = React.createClass({ diff --git a/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee index 5a4450313..0ee8dc023 100644 --- a/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee @@ -2,7 +2,6 @@ context = window rest = context.JK.Rest() SessionActions = @SessionActions JamTrackActions = @JamTrackActions -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup MIX_MODES = context.JK.MIX_MODES EVENTS = context.JK.EVENTS ChannelGroupIds = context.JK.ChannelGroupIds @@ -302,9 +301,7 @@ ChannelGroupIds = context.JK.ChannelGroupIds

recorded audio

{contents}
- - {mediaTracks} - + {mediaTracks}
` diff --git a/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee index 7008bb761..2c1b6e6e3 100644 --- a/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee @@ -1,7 +1,6 @@ context = window MIX_MODES = context.JK.MIX_MODES SessionActions = context.SessionActions -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; @SessionMyTracks = React.createClass({ @@ -44,9 +43,7 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; {delayVstEnable}
{content} - - {tracks} - + {tracks}
` diff --git a/web/app/assets/javascripts/react-components/SessionNotifications.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionNotifications.js.jsx.coffee index 96941368b..17d6ed18d 100644 --- a/web/app/assets/javascripts/react-components/SessionNotifications.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionNotifications.js.jsx.coffee @@ -1,5 +1,4 @@ context = window -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup NotificationActions = @NotificationActions @SessionNotifications = React.createClass({ @@ -30,9 +29,8 @@ NotificationActions = @NotificationActions Clear Notifications
- {notifications} - +
` diff --git a/web/app/assets/javascripts/react-components/SessionOtherTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionOtherTracks.js.jsx.coffee index d138490e1..275de1f11 100644 --- a/web/app/assets/javascripts/react-components/SessionOtherTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionOtherTracks.js.jsx.coffee @@ -1,6 +1,5 @@ context = window MixerActions = context.MixerActions -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup @SessionOtherTracks = React.createClass({ @@ -88,9 +87,8 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
{content} - - {participants} - + {participants} +
` diff --git a/web/app/assets/javascripts/react-components/actions/CallbackActions.js.coffee b/web/app/assets/javascripts/react-components/actions/CallbackActions.js.coffee new file mode 100644 index 000000000..92a639e88 --- /dev/null +++ b/web/app/assets/javascripts/react-components/actions/CallbackActions.js.coffee @@ -0,0 +1,6 @@ +context = window + +@CallbackActions = Reflux.createActions({ + genericCallback: {} +}) + diff --git a/web/app/assets/javascripts/react-components/actions/JamBlasterActions.js.coffee b/web/app/assets/javascripts/react-components/actions/JamBlasterActions.js.coffee new file mode 100644 index 000000000..82215844c --- /dev/null +++ b/web/app/assets/javascripts/react-components/actions/JamBlasterActions.js.coffee @@ -0,0 +1,10 @@ +context = window + +@JamBlasterActions = Reflux.createActions({ + resyncBonjour: {}, + clearPortBindState: {}, + saveNetworkSettings: {}, + pairState: {}, + setAutoPair: {}, + updateAudio: {} +}) diff --git a/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee b/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee index 590848abc..aa28215d6 100644 --- a/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee +++ b/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee @@ -674,7 +674,7 @@ MIX_MODES = context.JK.MIX_MODES; oppositeMixer = oppositeMixers[ChannelGroupIds.UserMusicInputGroup][0] if !oppositeMixer - logger.warn("unable to find UserMusicInputGroup corresponding to PeerAudioInputMusicGroup mixer", mixer ) + logger.warn("unable to find UserMusicInputGroup corresponding to PeerAudioInputMusicGroup mixer", mixer, @personalMixers ) when MIX_MODES.PERSONAL mixers = @groupedMixersForClientId(client_id, [ ChannelGroupIds.UserMusicInputGroup], {}, MIX_MODES.PERSONAL) diff --git a/web/app/assets/javascripts/react-components/mixins/BonjourMixin.js.coffee b/web/app/assets/javascripts/react-components/mixins/BonjourMixin.js.coffee index 504600c92..3c8da5f24 100644 --- a/web/app/assets/javascripts/react-components/mixins/BonjourMixin.js.coffee +++ b/web/app/assets/javascripts/react-components/mixins/BonjourMixin.js.coffee @@ -2,96 +2,16 @@ context = window teacherActions = window.JK.Actions.Teacher @BonjourMixin = { - - resyncBonjour: () -> - rest.getUserJamBlasters({client_id: @app.clientId}).done((response) => @getUserJamBlastersDone(response)).fail((response) => @getUserJamBlastersFail(response)) - - getUserJamBlastersDone: (response) -> - @setState({userJamBlasters: response}) - - @getLocalClients(response) - - - findJamBlaster: (id) -> + findJamBlaster: (oldClient) -> found = null - if @clients? - for client in @clients - if client.id == id + if @state.allJamBlasters? + for client in @state.allJamBlasters + if oldClient.server_id? && client.server_id == oldClient.server_id found = client break - if client.ipv6_addr == id + if oldClient.ipv6_addr? && client.ipv6_addr == oldClient.ipv6_addr found = client break found - - getUserJamBlastersFail: (jqXHR) -> - @app.layout.ajaxError(jqXHR) - - mergeBonjourClients: (localClients, userJamBlasters) -> - console.log("@state.localClients", localClients) - console.log("@state.userJamBlasters", userJamBlasters) - - # for localClient in @state.localClients - - for localClient in localClients - if localClient.connect_url.indexOf(':30330') && localClient.is_jb - client = {} - client.ipv6_addr = localClient.ipv6_addr - client.isPaired = localClient.isPaired - client.name = localClient.name - client.has_local = true - client.has_server = false - client.id = client.ipv6_addr - client.connect_url = localClient.connect_url - - - for serverClient in userJamBlasters - # see if we can join on ipv6 - if ipv6_addr == serverClient.ipv6_link_local - # ok, matched! augment with server data - client.serial_no = serverClient.serial_no - client.user_id = serverClient.user_id - client.id = serverClient.id - client.client_id = serverClient.client_id - client.ipv4_link_local = serverClient.ipv4_link_local - client.display_name = serverClient.display_name - client.has_server = true - break - clients.push(client) - - for serverClient in userJamBlasters - - foundLocal = false - for localClient in localClients - if ipv6_addr == serverClient.ipv6_link_local - foundLocal = true - break - if !foundLocal - # this server version of the client has not been spoken for in the earlier loop above - # so we need to add it in to the client list - - client = {} - client.serial_no = serverClient.serial_no - client.user_id = serverClient.user_id - client.id = serverClient.id - client.client_id = serverClient.client_id - client.ipv4_link_local = serverClient.ipv4_link_local - client.display_name = serverClient.display_name - client.has_local = false - client.has_server = true - clients.push(client) - - console.log("all client", clients) - - @clients = clients - @setState({clients: clients}) - - getLocalClients: (userJamBlasters) -> - localClients = context.jamClient.getLocalClients() - - @mergeBonjourClients(localClients, userJamBlasters) - - @setState({localClients: localClients}) - } \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee b/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee new file mode 100644 index 000000000..43f545ecf --- /dev/null +++ b/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee @@ -0,0 +1,24 @@ +$ = jQuery +context = window +logger = context.JK.logger +SessionActions = @SessionActions +JamBlasterActions = @JamBlasterActions + +@CallbackStore = Reflux.createStore( + { + init: () -> + # Register with the app store to get @app + this.listenTo(context.AppStore, this.onAppInit) + + onAppInit: (@app) -> + if context.jamClient.RegisterGenericCallBack? + context.jamClient.RegisterGenericCallBack('CallbackActions.genericCallback') + + onGenericCallback: (map) -> + if map.cmd == 'join_session' + SessionActions.joinSession(map['music_session_id']) + else if map.cmd == 'client_pair_state' + JamBlasterActions.pairState(map) + + } +) diff --git a/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee b/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee new file mode 100644 index 000000000..d87bb94f7 --- /dev/null +++ b/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee @@ -0,0 +1,345 @@ +$ = jQuery +context = window +logger = context.JK.logger + +@JamBlasterStore = Reflux.createStore( + { + listenables: @JamBlasterActions + + userJamBlasters: [] + localJamBlasters: [] + allJamBlasters: [] + + init: () -> + # Register with the app store to get @app + this.listenTo(context.AppStore, this.onAppInit) + + onAppInit: (@app) -> + + onUpdateAudio: (name, value) -> + # input1_linemode + # input2_linemode + # input1_48V + # input2_48V + # has_chat + # track1 = {left, right, inst, stereo) + # track1 = {left, right, inst, stereo) + + + if @pairedJamBlaster? && @pairedJamBlaster.tracks? + logger.debug("onUpdateAudio name=#{name} value=#{value}", @pairedJamBlaster.tracks) + audio = jQuery({}, @pairedJamBlaster.tracks) + if name == 'inputTypeTrack1' + audio.input1_linemode = value + else if name == 'inputTypeTrack2' + audio.input2_linemode = value + else if name == 'track1Phantom' + audio.input1_48V = value + else if name == 'track2Phantom' + audio.input2_48V = value + else if name == 'micActive' + audio.has_chat = value + + track1Active = @pairedJamBlaster.tracks.track1Active + if name == 'track1Active' + track1Active = value + + track2Active = @pairedJamBlaster.tracks.track2Active + if name == 'track2Active' + track2Active = value + + combined = @pairedJamBlaster.tracks.combined + if name == 'combined' + combined = value + + track1Instrument = audio.track1Instrument + track2Instrument = audio.track2Instrument + if name == 'track1Instrument' + track1Instrument = @convertToClientInstrument(value) + if name == 'track2Instrument' + track2Instrument = @convertToClientInstrument(value) + + + + + if combined + # user has chosen to combine both inputs into one track. stereo=true is the key flag her + + audio.track1 = {stereo: true, left: true, inst: track1Instrument} + + else + + if track1Active && track2Active + + audio.track1 = {stereo: false, left: true, inst: track1Instrument} + audio.track2 = {stereo: false, right: true, inst: track2Instrument} + + else if track1Active #(means track) + + audio.track1 = {stereo: false, left: true, inst: track1Instrument} + + else # input2Active + + audio.track2 = {stereo: false, right: true, inst: track2Instrument} + + + + + logger.debug("updating JamBlaster track state", audio) + context.jamClient.setJbTrackState(audio); + else + context.JK.Banner.showAlert('no paired JamBlaster', 'it seems your JamBlaster has become disconnected. Please ensure it is powered on and connected via an ethernet cable.') + + convertToClientInstrument: (instrumentId) -> + clientInstrumentId = null + if instrumentId != null && instrumentId != '' + clientInstrumentId = context.JK.instrument_id_to_instrument[instrumentId].client_id + else + clientInstrumentId = 10 + clientInstrumentId + + onSetAutoPair: (autopair) -> + + + if !autopair + context.jamClient.setJBAutoPair(autopair) + @lastClientAutoPair = null + JamBlasterActions.resyncBonjour() + setTimeout((() => context.JK.Banner.showNotice("autoconnect removed", + "To use the JamBlaster in the future, you will need to come to this screen and click the connect link.")), 1) + else + context.JK.Banner.showYesNo({ + title: "enable auto-connect", + html: "If you would like to automatically connect to your JamBlaster whenever you start this app, click the AUTO CONNECT button below.", + yes_text: 'AUTO CONNECT', + yes: => + context.jamClient.setJBAutoPair(autopair) + @lastClientAutoPair = null + JamBlasterActions.resyncBonjour() + setTimeout((() => context.JK.Banner.showNotice("autoconnect enabled", + "Your desktop JamKazam application will automatically reconnect to the JamBlaster .")), 1) + + }) + + onPairState: (state) -> + if state.client_pair_state == 10 + # fully paired + logger.debug("backend indicates we are paired with a client") + @onResyncBonjour() + + onSaveNetworkSettings: (settings) -> + logger.debug("onSaveNetworkSettings", settings) + + result = context.jamClient.setJbNetworkState(settings) + if !result + context.JK.Banner.showAlert('unable to save network settings', 'Please double-check that your JamBlaster is online and paired.') + return + else + context.JK.Banner.showAlert('network settings updated', 'Please reboot the JamBlaster.') + # it will be refreshed by backend + @onClearNetworkState() + @onResyncBonjour() + + onResyncBonjour: () -> + + if @refreshingBonjour + logger.debug("already refreshing bonjour") + return + + @refreshingBonjour = true + @changed() + rest.getUserJamBlasters({client_id: @app.clientId}).done((response) => @getUserJamBlastersDone(response)).fail((response) => @getUserJamBlastersFail(response)) + + getUserJamBlastersDone: (response) -> + @userJamBlasters = response + + @changed() + + @getLocalClients(response) + + + findJamBlaster: (oldClient) -> + found = null + if @clients? + for client in @clients + if oldClient.server_id? && client.server_id == oldClient.server_id + found = client + break + if oldClient.ipv6_addr? && client.ipv6_addr == oldClient.ipv6_addr + found = client + break + + found + + getUserJamBlastersFail: (jqXHR) -> + @refreshingBonjour = false + @changed() + @app.layout.ajaxError(jqXHR) + + getAutoPair: () -> + if @lastClientAutoPair? + return @lastClientAutoPair + else + return @getJbAutoPair() + + getNetworkState: (client) -> + if @lastClientNetworkState? && @lastClientNetworkState.ipv6_addr == client.ipv6_addr + return @lastClientNetworkState + else + return @getJbNetworkState(client) + + getPortState: (client) -> + if @lastClientPortState? && @lastClientPortState.ipv6_addr == client.ipv6_addr + return @lastClientPortState + else + return @getJbPortBindState(client) + + getJbPortBindState:(client) -> + @lastClientPortState = context.jamClient.getJbPortBindState() + console.log("context.jamClient.getJbPortBindState()", @lastClientPortState) + @lastClientPortState.ipv6_addr = client.ipv6_addr + return @lastClientPortState + + getJbNetworkState:(client) -> + @lastClientNetworkState = context.jamClient.getJbNetworkState() + console.log("context.jamClient.getJbNetworkState()", @lastClientNetworkState) + @lastClientNetworkState.ipv6_addr = client.ipv6_addr + return @lastClientNetworkState + + getJbAutoPair:() -> + @lastClientAutoPair = context.jamClient.getJBAutoPair() + console.log("context.jamClient.getJBAutoPair()", @lastClientAutoPair) + return @lastClientAutoPair + + getJbTrackState:(client) -> + @lastClientTrackState = context.jamClient.getJbTrackState() + console.log("context.jamClient.getJbTrackState()", @lastClientTrackState) + @lastClientTrackState.ipv6_addr = client.ipv6_addr + return @lastClientTrackState + + onClearPortBindState: () -> + @lastClientPortState = null + + onClearNetworkState: () -> + @lastClientNetworkState = null + + mergeBonjourClients: (localClients, userJamBlasters) -> + console.log("@state.localClients", localClients) + console.log("@state.userJamBlasters", userJamBlasters) + + # for localClient in @state.localClients + + autoconnect = @getAutoPair() + + foundPaired = null + clients = [] + for localClient in localClients + if localClient.connect_url.indexOf(':30330') > -1 && localClient.is_jb + client = {} + client.ipv6_addr = localClient.ipv6_addr + client.isConnected = localClient.isPaired + client.name = localClient.name + client.has_local = true + client.has_server = false + client.id = client.ipv6_addr + client.connect_url = localClient.connect_url + client.isPaired = localClient.pstate? && localClient.pstate == 10 # ePairingState.Paired + client.autoconnect = autoconnect + + if client.isPaired + client.portState = @getPortState(client) + client.network = @getNetworkState(client) + client.tracks = @getJbTrackState(client) + client.isDynamicPorts = client.portState?.use_static_port + foundPaired = client + + + if client.tracks? + client.tracks.inputTypeTrack1 = client.tracks.input1_linemode + client.tracks.inputTypeTrack2 = client.tracks.input2_linemode + client.tracks.track1Phantom = client.tracks.input1_48V + client.tracks.track2Phantom = client.tracks.input2_48V + client.tracks.micActive = client.tracks.has_chat + + # combined + track1 = client.tracks.track1 + track2 = client.tracks.track1 + if track1? + + client.tracks.combined = track1.stereo + if track1.stereo + client.tracks.track1Active = true + client.tracks.track2Active = true + client.tracks.track1Active = track1.left + client.tracks.track2Active = track1.right + client.tracks.track1Instrument = track1.inst + + if track2? + client.tracks.track2Instrument = track2.inst + client.tracks.track1Active = track2.left + client.tracks.track2Active = track2.right + # map["adaptiveframe"] = jbcfg.adaptiveframe(); + + + + + + + for serverClient in userJamBlasters + # see if we can join on ipv6 + if ipv6_addr == serverClient.ipv6_link_local + # ok, matched! augment with server data + client.serial_no = serverClient.serial_no + client.user_id = serverClient.user_id + client.id = serverClient.id + client.server_id = serverClient.id + client.client_id = serverClient.client_id + client.ipv4_link_local = serverClient.ipv4_link_local + client.display_name = serverClient.display_name + client.has_server = true + break + clients.push(client) + + for serverClient in userJamBlasters + + foundLocal = false + for localClient in localClients + if ipv6_addr == serverClient.ipv6_link_local + foundLocal = true + break + if !foundLocal + # this server version of the client has not been spoken for in the earlier loop above + # so we need to add it in to the client list + + client = {} + client.serial_no = serverClient.serial_no + client.user_id = serverClient.user_id + client.id = serverClient.id + client.client_id = serverClient.client_id + client.ipv4_link_local = serverClient.ipv4_link_local + client.display_name = serverClient.display_name + client.has_local = false + client.has_server = true + client.autoconnect = autoconnect + clients.push(client) + + @pairedJamBlaster = foundPaired + + console.log("all client", clients) + + @clients = clients + @changed() + + getLocalClients: (userJamBlasters) -> + @localClients = context.jamClient.getLocalClients() + + @mergeBonjourClients(@localClients, userJamBlasters) + + @refreshingBonjour = false + @changed() + + + changed: () -> + @trigger({userJamBlasters: @userJamBlasters, allJamBlasters: @clients, localJamBlasters: @localClients, refreshingBonjour: @refreshingBonjour, pairedJamBlaster: @pairedJamBlaster}) + } +) diff --git a/web/app/assets/javascripts/trackHelpers.js b/web/app/assets/javascripts/trackHelpers.js index d89b9b3f7..bdfd4d687 100644 --- a/web/app/assets/javascripts/trackHelpers.js +++ b/web/app/assets/javascripts/trackHelpers.js @@ -101,7 +101,16 @@ track.instrument_id = context.JK.server_to_client_instrument_map["Other"].server_id; } else { - track.instrument_id = context.JK.client_to_server_instrument_map[localMusicTracks[i].instrument_id].server_id; + + var instrument = context.JK.client_to_server_instrument_map[localMusicTracks[i].instrument_id] + if (instrument) { + track.instrument_id = instrument.server_id + } + else { + logger.debug("backend reported an invalid instrument ID of " + localMusicTracks[i].instrument_id) + track.instrument_id = 'other' + } + } if (localMusicTracks[i].stereo) { track.sound = "stereo"; diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index a4bb5d3aa..cf800db15 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -688,6 +688,15 @@ return instrumentArray; } + context.JK.convertClientInstrumentToServer = function(clientId) { + var serverInstrument = context.JK.client_to_server_instrument_map[clientId] + + if (!serverInstrument) + return 'other' + else + return serverInstrument.server_id + } + context.JK.showErrorDialog = function (app, msg, title) { app.layout.showDialog('error-dialog'); $('#error-msg', 'div[layout-id="error-dialog"]').html(msg); diff --git a/web/app/assets/stylesheets/client/content.css.scss b/web/app/assets/stylesheets/client/content.css.scss index a9292790a..6175b459a 100644 --- a/web/app/assets/stylesheets/client/content.css.scss +++ b/web/app/assets/stylesheets/client/content.css.scss @@ -453,7 +453,7 @@ ul.shortcuts { padding:2px; } - .account-home, .band-setup, .account-menu-group, .get-help, .community-forum, .invite-friends { + .account-home, .band-setup, .account-menu-group, .get-help, .community-forum, .invite-friends, .jamblaster-config { border-bottom:1px; border-style:solid; border-color:#ED3618; diff --git a/web/app/assets/stylesheets/client/jamblasterOptions.css.scss b/web/app/assets/stylesheets/client/jamblasterOptions.css.scss index 187dbb767..f06e59613 100644 --- a/web/app/assets/stylesheets/client/jamblasterOptions.css.scss +++ b/web/app/assets/stylesheets/client/jamblasterOptions.css.scss @@ -11,6 +11,10 @@ border-bottom:0 !important; } + &.isDynamicPorts .bt-content{ + width:140px !important; + } + .bt-content { height:80px; width:100px; diff --git a/web/app/assets/stylesheets/client/react-components/JamBlasterScreen.css.scss b/web/app/assets/stylesheets/client/react-components/JamBlasterScreen.css.scss index 23d93c0dc..d8e84f6e0 100644 --- a/web/app/assets/stylesheets/client/react-components/JamBlasterScreen.css.scss +++ b/web/app/assets/stylesheets/client/react-components/JamBlasterScreen.css.scss @@ -5,12 +5,40 @@ div[data-react-class="JamBlasterScreen"] { height:100%; } + + + h3 { + font-weight:bold; + font-size:18px; + color:white; + margin-bottom:20px; + } + + h4 { + font-size:16px; + color:white; + font-weight:bold; + margin:30px 0 10px 0; + } .content-body-scroller { height:100%; padding:30px; @include border_box_sizing; } + .column { + float:left; + width:50%; + @include border_box_sizing; + + &.column-left { + padding-right:20px; + } + &.column-right { + padding-left:20px; + } + } + ol { li { margin-left:15px; @@ -20,6 +48,58 @@ } } + .tiles { + float:right; + margin-bottom: 40px; + margin-top: -3px; + } + .jamblaster-tile { + float:left; + @include border-box_sizing; + width:117px; + border-radius:4px; + margin-left:7px; + height: 32px; + line-height:32px; + position: relative; + background-color:#535353; + + &.activeTile + { + background-color: #ed3618; + } + + a { + position: absolute; + text-align: center; + bottom:0; + left:0; + width: 100%; + margin: 0 auto; + padding: 0 10px 0; + color:white; + background-color:transparent; + @include border-box_sizing; + } + } + + .networking-content { + .field { + margin-bottom:10px; + } + .iradio_minimal { + display: inline-block; + top: 4px; + margin-right: 5px; + } + label { + display:inline-block; + } + .dhcpfield { + margin-bottom:10px; + } + } + .student-right-content { p { margin-bottom:10px; @@ -35,28 +115,11 @@ } } h2 { - font-size: 20px; + font-size: 22px; font-weight:700; - margin-bottom: 20px !important; + margin-bottom: 40px !important; display:inline-block; } - .column { - @include border_box_sizing; - width:50%; - } - .column-left { - float:left; - width:70%; - } - .column-right { - float:right; - width:30%; - padding-left:20px; - - .jamclass-section { - padding-top:36px; - } - } span.price { color:white; } @@ -112,7 +175,7 @@ height:100%; width:100%; table-layout:fixed; - margin-bottom:20px; + margin-bottom:10px; a { text-decoration: none !important; color:#fc0 !important; @@ -178,4 +241,55 @@ } } } + .resync-bonjour { + float:right; + margin-right:3px; + margin-bottom:20px; + width:110px; + } + p.help-text { + clear:both; + } + .save-settings-btn { + width:200px; + } + .manual-settings { + margin:20px 0; + label { + display:inline-block; + color: $ColorTextTypical; + width: 90px; + text-align: right; + padding-right: 10px; + } + input { + display:inline-block; + + } + } + .status-label { + width:80px; + display:inline-block; + } + .status-field { + margin-bottom:10px; + color:$ColorTextTypical; + } + + .input-1 { + @include border-box_sizing; + width:200px; + margin-right:20px; + } + + .input-2 { + @include border-box_sizing; + width:200px; + margin-right:20px; + } + + .microphone { + @include border-box_sizing; + width:200px; + } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/react-components/JamBlasterTrackConfig.css.scss b/web/app/assets/stylesheets/client/react-components/JamBlasterTrackConfig.css.scss new file mode 100644 index 000000000..795d928cb --- /dev/null +++ b/web/app/assets/stylesheets/client/react-components/JamBlasterTrackConfig.css.scss @@ -0,0 +1,80 @@ +@import "client/common"; + +.jamblaster-track-config { + + + h3 { + font-weight:bold; + font-size:18px; + color:white; + margin-bottom:10px; + width:100%; + border-width:0 0 1px 0; + border-color: $ColorTextTypical; + border-style:solid; + padding-bottom:5px; + } + + h4 { + font-size:14px; + color:white; + margin:0 0 10px 0; + } + + .input-1 { + position:relative; + @include border-box_sizing; + width:200px; + margin-right:20px; + float:left; + } + + .input-2 { + position:relative; + @include border-box_sizing; + width:200px; + margin-right:20px; + float:left; + } + + .microphone { + position:relative; + @include border-box_sizing; + width:200px; + float:left; + } + + .iradio_minimal { + display: inline-block; + top: 4px; + margin-right: 5px; + } + + .icheckbox_minimal { + display: inline-block; + top: 2px; + margin-right: 5px; + } + label { + display:inline-block; + } + .input-type-section { + margin:20px 0 30px; + } + .phantom-section { + margin:20px 0 30px; + } + .instrument-section { + margin:20px 0 30px; + } + .track-active-field { + position:absolute; + top:-4px; + right:0; + } + .input-type-choice { + &:first-of-type { + margin-bottom:10px; + } + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss b/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss index aa776ede7..c3440c414 100644 --- a/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss +++ b/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss @@ -65,7 +65,7 @@ .tab { padding-top:20px; } - .tab[tab-id="music-audio"] { + .tab[data-tab-id="music-audio"] { .column { &:nth-of-type(1) { width: 30%; @@ -87,7 +87,7 @@ } } - .tab[tab-id="voice-chat"] { + .tab[data-tab-id="voice-chat"] { .column { &:nth-of-type(1) { width: 50%; diff --git a/web/app/assets/stylesheets/dialogs/jamblasterNameDialog.css.scss b/web/app/assets/stylesheets/dialogs/jamblasterNameDialog.css.scss index eaf1ea52c..fd2fdbc5c 100644 --- a/web/app/assets/stylesheets/dialogs/jamblasterNameDialog.css.scss +++ b/web/app/assets/stylesheets/dialogs/jamblasterNameDialog.css.scss @@ -35,6 +35,9 @@ } .actions { float:right; - margin:0 -13px 30px 0; + margin:20px 0 30px 0; + } + .help-text { + margin:0 0 20px 0; } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/dialogs/jamblasterPairingDialog.css.scss b/web/app/assets/stylesheets/dialogs/jamblasterPairingDialog.css.scss index 86c0b6bdb..071b9c176 100644 --- a/web/app/assets/stylesheets/dialogs/jamblasterPairingDialog.css.scss +++ b/web/app/assets/stylesheets/dialogs/jamblasterPairingDialog.css.scss @@ -2,7 +2,6 @@ #jamblaster-pairing-dialog { width: 600px; - max-height:600px; h2 { color:white; @@ -11,7 +10,8 @@ } .dialog-inner { width: auto; - height:calc(100% - 29px) + height:calc(100% - 29px); + padding-bottom:75px; } .field { @@ -34,8 +34,13 @@ } .actions { - float:right; - margin:0 -13px 30px 0; + position:absolute; + right:0; + bottom:0; + margin:0 20px 30px 0; + } + .countdown-msg { + margin-top:30px; } .countdown { color:white; @@ -44,5 +49,9 @@ padding:0 10px; width:30px; display:inline-block; + text-align:center; + } + .message { + margin-top:20px; } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/dialogs/jamblasterPortDialog.css.scss b/web/app/assets/stylesheets/dialogs/jamblasterPortDialog.css.scss new file mode 100644 index 000000000..c0527d115 --- /dev/null +++ b/web/app/assets/stylesheets/dialogs/jamblasterPortDialog.css.scss @@ -0,0 +1,43 @@ +@import "client/common"; + +#jamblaster-port-dialog { + width: 600px; + max-height:600px; + + h2 { + color:white; + margin-bottom:10px; + font-size:16px; + } + .dialog-inner { + width: auto; + height:calc(100% - 29px) + } + + .field { + margin-bottom:10px; + } + + input { + display:inline-block; + } + label { + display:inline-block; + } + .iradio_minimal { + display:inline-block; + margin-right: 5px; + top: 4px; + } + + div[data-react-class="JamBlasterNameDialog"] { + + } + .actions { + float:right; + margin:20px 0 30px 0; + } + .help-text { + margin:0 0 20px 0; + } +} \ No newline at end of file diff --git a/web/app/views/clients/_jamblasterOptions.html.slim b/web/app/views/clients/_jamblasterOptions.html.slim index a9f22181a..cc47e32b2 100644 --- a/web/app/views/clients/_jamblasterOptions.html.slim +++ b/web/app/views/clients/_jamblasterOptions.html.slim @@ -1,8 +1,13 @@ script type='text/template' id='template-jamblaster-options' ul + = '{% if (data.autoconnect) { %}' + li data-jamblaster-option="auto-connect" + a href='#' Cancel Auto Connect + = '{% } else { %}' li data-jamblaster-option="auto-connect" a href='#' Auto Connect + = '{% } %}' li data-jamblaster-option="restart" a href='#' Restart @@ -13,8 +18,12 @@ script type='text/template' id='template-jamblaster-options' li data-jamblaster-option="check-for-updates" a href='#' Check for Updates + = '{% if (data.isDynamicPorts) { %}' + li data-jamblaster-option="set-static-ports" + a href='#' Revert To Dynamic Ports + = '{% } else { %}' li data-jamblaster-option="set-static-ports" a href='#' Set Static Ports - + = '{% } %}' li data-jamblaster-option="factory-reset" a href='#' Factory Reset diff --git a/web/app/views/dialogs/_clientPreferencesDialog.html.slim b/web/app/views/dialogs/_clientPreferencesDialog.html.slim index a347c1ceb..cf17266ca 100644 --- a/web/app/views/dialogs/_clientPreferencesDialog.html.slim +++ b/web/app/views/dialogs/_clientPreferencesDialog.html.slim @@ -19,7 +19,7 @@ .input input type="number" name="static-port" label for="static-port" The first port that the client will open - p.hint You can specify any port you like, but we recommend an even number in the range including 1026-49150 to avoid conflicts with other programs. When configuring Port Forwarding in your router, be sure to open this port along with the next ten. For example, if this field is 12000, then in your router, forward ports 12000-12010 to your computer's IP address. + p.hint You can specify any port you like, but we recommend an even number in the range including 1026-49150 to avoid conflicts with other programs. When configuring Port Forwarding in your router, be sure to open this port along with the next 10. For example, if this field is 12000, then in your router, forward ports 12000-12010 to your computer's IP address. br clear='all' br clear='all' .buttons diff --git a/web/app/views/dialogs/_configure_tracks_dialog.html.haml b/web/app/views/dialogs/_configure_tracks_dialog.html.haml index 42d6d1d2e..b34997d19 100644 --- a/web/app/views/dialogs/_configure_tracks_dialog.html.haml +++ b/web/app/views/dialogs/_configure_tracks_dialog.html.haml @@ -3,51 +3,4 @@ = image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' } %h1 configure tracks .dialog-inner - .dialog-tabs - %a.selected.tab-configure-audio Inputs & Outputs - %a.tab-configure-voice Voice Chat - - .instructions - %span - Choose your audio device. Drag and drop to assign input ports to tracks, and specify the instrument - for each track. Drag and drop to assign a pair of output ports for session stereo audio monitoring. - - .clearall - - .tab.no-selection-range{'tab-id' => 'music-audio'} - - = react_component 'ConfigureTracks', {} - - .clearall - - - - .tab{'tab-id' => 'voice-chat'} - - %form.select-voice-chat-option.section.voice - .sub-header Select Voice Chat Option - .voicechat-option.reuse-audio-input - %input{type:"radio", name: "voicechat", checked:"checked"} - %h3 Use Music Microphone - %p I am already using a microphone to capture my vocal or instrumental music, so I can talk with other musicians using that microphone - .voicechat-option.use-chat-input - %input{type:"radio", name: "voicechat"} - %h3 Use Chat Microphone - %p I am not using a microphone for acoustic instruments or vocals, so use the input selected to the right for voice chat during my sessions - .clearall - .select-voice-chat - .sub-header Voice Chat Input - .ftue-box.chat-inputs - .vu-meter - .ftue-controls - .ftue-vu-left.voice-chat-vu-left - .ftue-fader.chat-fader - .gain-label GAIN - .ftue-vu-right.voice-chat-vu-right - .clearall - - .buttons - %a.btn-add-new-audio-gear.button-grey{'layout-link' => 'add-new-audio-gear'} ADD NEW AUDIO GEAR - %a.button-grey.btn-cancel{href:'#'} CANCEL - %a.button-orange.btn-update-settings{href:'#'} SAVE SETTINGS - + = react_component 'ConfigureTracksDialogContents', {} \ No newline at end of file diff --git a/web/app/views/dialogs/_dialogs.html.haml b/web/app/views/dialogs/_dialogs.html.haml index 9e2b83c75..f76211f13 100644 --- a/web/app/views/dialogs/_dialogs.html.haml +++ b/web/app/views/dialogs/_dialogs.html.haml @@ -57,4 +57,5 @@ = render 'dialogs/musicNotationUploadDialog' = render 'dialogs/testDrivePackageDialog' = render 'dialogs/jamblasterNameDialog' += render 'dialogs/jamblasterPortDialog' = render 'dialogs/jamblasterPairingDialog' \ No newline at end of file diff --git a/web/app/views/dialogs/_jamblasterPortDialog.html.slim b/web/app/views/dialogs/_jamblasterPortDialog.html.slim new file mode 100644 index 000000000..90f17a5cf --- /dev/null +++ b/web/app/views/dialogs/_jamblasterPortDialog.html.slim @@ -0,0 +1,2 @@ +.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='jamblaster-port-dialog' id='jamblaster-port-dialog' + = react_component 'JamBlasterPortDialog', {} diff --git a/web/app/views/users/_user_dropdown.html.erb b/web/app/views/users/_user_dropdown.html.erb index c32e894a0..761d681cf 100644 --- a/web/app/views/users/_user_dropdown.html.erb +++ b/web/app/views/users/_user_dropdown.html.erb @@ -47,6 +47,9 @@ <% if current_user && current_user.affiliate_partner.present? %> <% end %> + <% if @nativeClient %> +
  • <%= link_to "JamBlaster", '/client#/jamblaster' %>
  • + <% end %> <% if current_user && current_user.musician? %>
  • <%= link_to "Band Setup", '/client#/band/setup/new' %>
  • <% end %> diff --git a/web/lib/tasks/jam_tracks.rake b/web/lib/tasks/jam_tracks.rake index dc8a4e9d5..dd4d95efa 100644 --- a/web/lib/tasks/jam_tracks.rake +++ b/web/lib/tasks/jam_tracks.rake @@ -1,7 +1,7 @@ namespace :jam_tracks do task import_click_tracks: :environment do |task, args| - JamTrackImporter.storage_format = 'Tency' + JamTrackImporter.storage_format = 'Helbing' JamTrackImporter.import_click_tracks end @@ -124,8 +124,8 @@ namespace :jam_tracks do end task resync_instruments: :environment do |task, args| - JamTrackImporter.storage_format = 'Paris' - JamTrackImporter.resync_instruments(JamTrackLicensor.find_by_name!('Paris Music')) + JamTrackImporter.storage_format = ENV['STORAGE_FORMAT'] + JamTrackImporter.resync_instruments(JamTrackLicensor.find_by_name!('Stockton Helbing')) end @@ -249,6 +249,11 @@ namespace :jam_tracks do JamTrackImporter.synchronize_jamtrack_aac_previews end + task sync_click_mp3_to_wav: :environment do |task, args| + JamTrackImporter.storage_format = 'Helbing' + JamTrackImporter.convert_click_track_to_wavs + end + # popuplate preview info without uploading/processing audio files (use what's in S3) task sync_previews_dev: :environment do |task, args| JamTrackImporter.synchronize_previews_dev