Merge video_ui branch into develop.

This commit is contained in:
Steven Miers 2015-04-21 13:47:00 -05:00
commit a9ab5bb730
31 changed files with 644 additions and 168 deletions

View File

@ -278,4 +278,4 @@ show_whats_next_count.sql
recurly_adjustments.sql
signup_hints.sql
packaging_notices.sql
first_played_jamtrack_at.sql
first_played_jamtrack_at.sql

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -8,8 +8,10 @@
var rest = context.JK.Rest();
var userId;
var user = {};
function beforeShow(data) {
console.log("beforeShow", data)
userId = data.id;
}
@ -43,6 +45,11 @@
var invalidProfiles = prettyPrintAudioProfiles(context.JK.getBadConfigMap());
var sessionSummary = summarizeSession(userDetail);
var webcam = context.jamClient.FTUECurrentSelectedVideoDevice
if (webcam==null || typeof(webcam)=="undefined" || webcam.length==0) {
webcam = "None Configured"
}
var $template = $(context._.template($('#template-account-main').html(), {
email: userDetail.email,
name: userDetail.name,
@ -56,6 +63,7 @@
invalidProfiles : invalidProfiles,
isNativeClient: gon.isNativeClient,
musician: context.JK.currentUserMusician,
webcamName: webcam,
sales_count: userDetail.sales_count
} , { variable: 'data' }));
@ -65,8 +73,9 @@
$('#account-scheduled-sessions-link').show();
} else {
$('#account-scheduled-sessions-link').hide();
}
}
}
}// function
function prettyPrintAudioProfiles(profileMap) {
var profiles = "";
@ -110,6 +119,7 @@
$('#account-content-scroller').on('click', '#account-edit-subscriptions-link', function(evt) { evt.stopPropagation(); navToEditSubscriptions(); return false; } );
$('#account-content-scroller').on('click', '#account-edit-payments-link', function(evt) { evt.stopPropagation(); navToEditPayments(); return false; } );
$('#account-content-scroller').on('click', '#account-edit-audio-link', function(evt) { evt.stopPropagation(); navToEditAudio(); return false; } );
$('#account-content-scroller').on('click', '#account-edit-video-link', function(evt) { evt.stopPropagation(); navToEditVideo(); return false; } );
$('#account-content-scroller').on('avatar_changed', '#profile-avatar', function(evt, newAvatarUrl) { evt.stopPropagation(); updateAvatar(newAvatarUrl); return false; })
// License dialog:
@ -158,6 +168,11 @@
window.location = "/client#/account/audio"
}
function navToEditVideo() {
resetForm()
window.location = "/client#/account/video"
}
function navToPaymentHistory() {
window.location = '/client#/account/paymentHistory'
}
@ -178,6 +193,7 @@
}
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow

View File

@ -0,0 +1,32 @@
(function (context, $) {
"use strict";
context.JK = context.JK || {};
context.JK.AccountVideoProfile = function (app) {
var $webcamViewer = new context.JK.WebcamViewer()
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,
'beforeHide':beforeHide
};
app.bindScreen('account/video', screenBindings);
$webcamViewer.init($(".webcam-container"))
}
function beforeShow() {
$webcamViewer.beforeShow()
}
function beforeHide() {
$webcamViewer.setVideoOff()
}
this.beforeShow = beforeShow
this.beforeHide = beforeHide
this.initialize = initialize
return this;
};
})(window, jQuery);

View File

@ -10,10 +10,10 @@
var $dialog = null;
function resetForm() {
// remove all display errors
$('#recording-finished-dialog form .error-text').remove()
$('#recording-finished-dialog form .error').removeClass("error")
removeGoogleLoginErrors()
}
function beforeShow() {
@ -130,11 +130,47 @@
return false;
}
function startGoogleLogin(e) {
e.preventDefault()
logger.debug("Starting google login")
window._oauth_win = window.open("/auth/google_login", "Log In to Google", "height=500,width=500,menubar=no,resizable=no,status=no");
window._oauth_callback = function() {
window._oauth_win.close()
setGoogleAuthState()
}
return false;
}
function claimRecording(e) {
resetForm();
registerClaimRecordingHandlers(false);
registerClaimRecordingHandlers(false)
var upload_to_youtube = $('#recording-finished-dialog form input[name=upload_to_youtube]').is(':checked')
if (upload_to_youtube) {
$.ajax({
type: "GET",
dataType: "json",
url: "/auth/has_google_auth"
}).success(function(data) {
if(data.has_google_auth) {
performClaim()
} else {
var error_ul = $('<ul class="error-text upload_to_youtube"><li>You must sign in to YouTube</li></ul>')
$('#recording-finished-dialog form [purpose=upload_to_youtube]').addClass('error').append(error_ul)
}
}).always(function () {
registerClaimRecordingHandlers(true);
})
} else {
performClaim()
}
return false;
}
function performClaim() {
var name = $('#recording-finished-dialog form input[name=name]').val();
var description = $('#recording-finished-dialog form textarea[name=description]').val();
var genre = $('#recording-finished-dialog form select[name=genre]').val();
@ -151,59 +187,53 @@
save_video: save_video,
upload_to_youtube: upload_to_youtube
})
.done(function () {
$dialog.data('result', {keep:true});
app.layout.closeDialog('recordingFinished');
context.JK.GA.trackMakeRecording();
})
.fail(function (jqXHR) {
if (jqXHR.status == 422) {
var errors = JSON.parse(jqXHR.responseText);
.done(function () {
$dialog.data('result', {keep:true});
app.layout.closeDialog('recordingFinished');
context.JK.GA.trackMakeRecording();
})
.fail(function (jqXHR) {
if (jqXHR.status == 422) {
var errors = JSON.parse(jqXHR.responseText);
var $name_errors = context.JK.format_errors('name', errors);
if ($name_errors) $('#recording-finished-dialog form input[name=name]').closest('div.field').addClass('error').end().after($name_errors);
var $name_errors = context.JK.format_errors('name', errors);
if ($name_errors) $('#recording-finished-dialog form input[name=name]').closest('div.field').addClass('error').end().after($name_errors);
var $description_errors = context.JK.format_errors('description', errors);
if ($description_errors) $('#recording-finished-dialog form input[name=description]').closest('div.field').addClass('error').end().after($description_errors);
var $description_errors = context.JK.format_errors('description', errors);
if ($description_errors) $('#recording-finished-dialog form input[name=description]').closest('div.field').addClass('error').end().after($description_errors);
var $genre_errors = context.JK.format_errors('genre', errors);
if ($genre_errors) $('#recording-finished-dialog form select[name=genre]').closest('div.field').addClass('error').end().after($genre_errors);
var $genre_errors = context.JK.format_errors('genre', errors);
if ($genre_errors) $('#recording-finished-dialog form select[name=genre]').closest('div.field').addClass('error').end().after($genre_errors);
var $is_public_errors = context.JK.format_errors('is_public', errors);
if ($is_public_errors) $('#recording-finished-dialog form input[name=is_public]').closest('div.field').addClass('error').end().after($is_public_errors);
var $is_public_errors = context.JK.format_errors('is_public', errors);
if ($is_public_errors) $('#recording-finished-dialog form input[name=is_public]').closest('div.field').addClass('error').end().after($is_public_errors);
var $save_video_errors = context.JK.format_errors('save_video', errors);
if ($save_video_errors) $('#recording-finished-dialog form input[name=save_video]').closest('div.field').addClass('error').end().after($save_video_errors);
var $save_video_errors = context.JK.format_errors('save_video', errors);
if ($save_video_errors) $('#recording-finished-dialog form input[name=save_video]').closest('div.field').addClass('error').end().after($save_video_errors);
var recording_error = context.JK.get_first_error('recording_id', errors);
var $upload_to_youtube_errors = context.JK.format_errors('upload_to_youtube', errors);
if ($upload_to_youtube_errors) $('#recording-finished-dialog form input[name=upload_to_youtube]').closest('div.field').addClass('error').end().after($upload_to_youtube_errors);
if (recording_error) context.JK.showErrorDialog(app, "Unable to claim recording.", recording_error);
}
else {
logger.error("unable to claim recording %o", arguments);
var recording_error = context.JK.get_first_error('recording_id', errors);
if (recording_error) context.JK.showErrorDialog(app, "Unable to claim recording.", recording_error);
}
else {
logger.error("unable to claim recording %o", arguments);
context.JK.showErrorDialog(app, "Unable to claim recording.", jqXHR.responseText);
}
})
.always(function () {
registerClaimRecordingHandlers(true);
});
return false;
context.JK.showErrorDialog(app, "Unable to claim recording.", jqXHR.responseText);
}
})
.always(function () {
registerClaimRecordingHandlers(true);
});
}
function registerClaimRecordingHandlers(onOff) {
$('#keep-session-recording').off('click', claimRecording)
$('#recording-finished-dialog form').off('submit', claimRecording);
if (onOff) {
$('#keep-session-recording').on('click', claimRecording);
$('#recording-finished-dialog form').on('submit', claimRecording);
}
else {
$('#keep-session-recording').off('click', claimRecording)
$('#recording-finished-dialog form').off('submit', claimRecording);
}
}
function registerDiscardRecordingHandlers(onOff) {
@ -237,6 +267,35 @@
.on('pause', onPause)
.on('play', onPlay)
.on('change-position', onChangePlayPosition);
$dialog.find(".google_login_button").on('click', startGoogleLogin);
// Check for google authorization using AJAX and show/hide the
// google login button / "signed in" label as appropriate:
$(window).on('focus', function() {
setGoogleAuthState();
});
}
function setGoogleAuthState() {
$.ajax({
type: "GET",
dataType: "json",
url: "/auth/has_google_auth"
}).success(function(data) {
if(data.has_google_auth) {
$("input.google_login_button").addClass("hidden")
$("span.signed_in_to_google").removeClass("hidden")
removeGoogleLoginErrors()
} else {
$("span.signed_in_to_google").addClass("hidden")
$("input.google_login_button").removeClass("hidden")
}
})
}
function removeGoogleLoginErrors() {
$("ul.error-text.upload_to_youtube").remove()
$('#recording-finished-dialog form div[purpose=upload_to_youtube]').removeClass('error')
}
function setRecording(recordingData) {
@ -267,7 +326,6 @@
playbackControls = new context.JK.PlaybackControls($('#recording-finished-dialog .recording-controls'));
registerStaticEvents();
initializeButtons();
};

View File

@ -21,6 +21,7 @@
var frameSize = 2.5;
var fakeJamClientRecordings = null;
var p2pCallbacks = null;
var videoShared = false;
var metronomeActive=false;
var metronomeBPM=false;
var metronomeSound=false;
@ -59,6 +60,41 @@
function FTUESetMusicProfileName() {
}
function FTUESelectVideoCaptureDevice(device, settings) {
}
function FTUESetVideoEncodeResolution(resolution) {
}
function FTUEGetVideoCaptureDeviceNames() {
return ["Built-in Webcam HD"]
}
function FTUECurrentSelectedVideoDevice() {
return "Built-in Webcam HD"
}
function FTUEGetAvailableEncodeVideoResolutions() {
return {
1: "1024x768",
2: "800x600"
}
}
function isSessVideoShared() {
return videoShared;
}
function SessStopVideoSharing() {
videoShared=false;
}
function SessStartVideoSharing(bitrate) {
if (!bitrate || typeof(bitrate)=="undefined") {
bitrate = 0
}
videoShared=true;
}
function FTUEGetInputLatency() {
dbg("FTUEGetInputLatency");
return 2;
@ -1151,6 +1187,17 @@
this.ClosePreviewRecording = ClosePreviewRecording;
this.OnDownloadAvailable = OnDownloadAvailable;
// Video functionality:
this.FTUESelectVideoCaptureDevice = FTUESelectVideoCaptureDevice
this.FTUESetVideoEncodeResolution = FTUESetVideoEncodeResolution;
this.FTUEGetVideoCaptureDeviceNames = FTUEGetVideoCaptureDeviceNames;
this.FTUECurrentSelectedVideoDevice = FTUECurrentSelectedVideoDevice;
this.FTUEGetAvailableEncodeVideoResolutions = FTUEGetAvailableEncodeVideoResolutions;
this.isSessVideoShared = isSessVideoShared;
this.SessStopVideoSharing = SessStopVideoSharing;
this.SessStartVideoSharing = SessStartVideoSharing;
// Clipboard
this.SaveToClipboard = SaveToClipboard;

View File

@ -937,6 +937,12 @@
}
}
if(optionRequiresMultiplayerProfile()) {
if(context.JK.guardAgainstSinglePlayerProfile(app).canPlay == false) {
return false;
}
}
var valid = beforeMoveStep();
if (!valid) {
return false;

View File

@ -13,6 +13,7 @@
var modUtils = context.JK.ModUtils;
var logger = context.JK.logger;
var self = this;
var webcamViewer = new context.JK.WebcamViewer()
var defaultParticipant = {
tracks: [{
@ -143,6 +144,7 @@
var shareDialog = new JK.ShareDialog(context.JK.app, sessionId, "session");
shareDialog.initialize(context.JK.FacebookHelperInstance);
webcamViewer.beforeShow()
}
function beforeDisconnect() {
@ -210,7 +212,6 @@
var singlePlayerCheckOK = true;
// to know whether we are allowed to be in this session, we have to check if we are the creator when checking against single player functionality
if(musicSession.user_id != context.JK.currentUserId) {
var canPlay = context.JK.guardAgainstSinglePlayerProfile(app, function () {
promptLeave = false;
});
@ -503,6 +504,7 @@
}
function beforeHide(data) {
webcamViewer.setVideoOff()
$fluidTracks.removeClass('showing');
if(screenActive) {
// this path is possible if FTUE is invoked on session page, and they cancel
@ -714,7 +716,7 @@
function _initDialogs() {
configureTrackDialog.initialize();
addNewGearDialog.initialize();
addNewGearDialog.initialize();
}
// Get the latest list of underlying audio mixer channels, and populates:
@ -2011,15 +2013,12 @@
var liveTrackWidthPct = Math.ceil(100 * liveTrackWidth/totalWidth);
//logger.debug("resizeFluid: ", minimumLiveTrackWidth, otherAudioWidth, otherAudioWidthPct, liveTrackWidthPct, liveTrackWidthPct)
$audioTracks.css('width', otherAudioWidthPct + '%');
$liveTracks.css('width', liveTrackWidthPct + '%');
}
function _addRecordingTrack(trackData, mixer, oppositeMixer) {
otherAudioFilled();
$('.session-recordings .recording-controls').show();
var parentSelector = '#session-recordedtracks-container';
@ -2479,6 +2478,18 @@
return false;
}
function sessionWebCam(e) {
e.preventDefault();
if(webcamViewer.isVideoShared()) {
$('#session-webcam').removeClass("selected")
} else {
$('#session-webcam').addClass("selected")
}
webcamViewer.toggleWebcam()
return false;
}
// http://stackoverflow.com/questions/2604450/how-to-create-a-jquery-clock-timer
function updateRecordingTimer() {
@ -2739,7 +2750,6 @@
}// function
function openBackingTrackFile(e) {
// just ignore the click if they are currently recording for now
if(sessionModel.recordingModel.isRecording()) {
app.notify({
@ -3075,7 +3085,6 @@
var mode = data.playbackMode; // will be either 'self' or 'cricket'
logger.debug("setting metronome playback mode: ", mode)
var isCricket = mode == 'cricket';
context.jamClient.setMetronomeCricketTestState(isCricket);
}
@ -3108,6 +3117,7 @@
function events() {
$('#session-leave').on('click', sessionLeave);
$('#session-resync').on('click', sessionResync);
$('#session-webcam').on('click', sessionWebCam);
$('#session-contents').on("click", '[action="delete"]', deleteSession);
$tracksHolder.on('click', 'div[control="mute"]', toggleMute);
$('#recording-start-stop').on('click', startStopRecording);
@ -3191,7 +3201,8 @@
$fluidTracks = $screen.find('.session-fluidtracks');
$voiceChat = $screen.find('#voice-chat');
$tracksHolder = $screen.find('#tracks')
webcamViewer.init($(".webcam-container"))
webcamViewer.setVideoOff()
events();

View File

@ -215,7 +215,7 @@
// see if we already have tracks; if so, we need to run with these
var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient);
console.log("isNoInputProfile", gearUtils.isNoInputProfile())
logger.debug("isNoInputProfile", gearUtils.isNoInputProfile())
if(inputTracks.length > 0 || gearUtils.isNoInputProfile() ) {
logger.debug("on page enter, tracks are already available")
sessionPageEnterDeferred.resolve(inputTracks);

View File

@ -0,0 +1,104 @@
$ = jQuery
context = window
context.JK ||= {};
context.JK.WebcamViewer = class WebcamViewer
constructor: (@root) ->
@client = context.jamClient
@logger = context.JK.logger
@initialScan = false
@toggleBtn = null
@webcamSelect = null
@resolutionSelect = null
@videoShared=false
@resolution=null
init: (root) =>
@logger.debug 'root', root
@root = root
@toggleBtn = @root.find(".webcam-test-btn")
@webcamSelect = @root.find(".webcam-select-container select")
@resolutionSelect = @root.find(".webcam-resolution-select-container select")
@webcamSelect.on("change", this.selectWebcam)
@logger.debug 'webcamSelect', @webcamSelect
beforeShow:() =>
this.loadWebCams()
this.selectWebcam()
this.loadResolutions()
this.selectResolution()
@initialScan = true
#client.SessSetInsetPosition(5)
#client.SessSetInsetSize(1)
#client.FTUESetAutoSelectVideoLayout(false)
#client.SessSelectVideoDisplayLayoutGroup(1)
selectWebcam:(e, data) =>
@logger.debug 'Selecting control: ', @webcamSelect
device = @webcamSelect.val()
if device != null and device != ''
@logger.debug 'Selecting webcam: ', device
selectResolution:() =>
@logger.debug 'Selecting res control: ', @resolutionSelect
@resolution = @resolutionSelect.val()
if @resolution != null and @resolution != ''
@logger.debug 'Selecting res: ', @resolution
@client.FTUESetVideoEncodeResolution @resolution
setVideoOff:() =>
if this.isVideoShared()
@client.SessStopVideoSharing()
isVideoShared:() =>
@videoShared
setToggleState:() =>
available = @webcamSelect.find('option').size() > 0
shared = this.isVideoShared()
@logger.debug 'Setting toggle from : ', shared
@toggleBtn.prop 'disabled', true
@toggleBtn.prop 'disabled', !available
toggleWebcam:() =>
@logger.debug 'Toggling webcam from: ', this.isVideoShared()
if this.isVideoShared()
@client.SessStopVideoSharing()
@videoShared = false
else
@client.SessStartVideoSharing 0
@videoShared = true
loadWebCams:() =>
devices = @client.FTUEGetVideoCaptureDeviceNames()
selectedDevice = @client.FTUECurrentSelectedVideoDevice()
selectControl = @webcamSelect
context._.each devices, (device) ->
selected = device == selectedDevice
option = $('<option/>',
id: device
value: device
text: device)
@logger.debug("Appending to: ", selectControl, option)
selectControl.append option
selectControl.val selectedDevice
if devices.length == 0
@root.find('.no-webcam-msg').removeClass 'hidden'
else
@root.find('.no-webcam-msg').addClass 'hidden'
loadResolutions:() =>
resolutions = @client.FTUEGetAvailableEncodeVideoResolutions()
selectControl = @resolutionSelect
@logger.debug 'FOUND THESE RESOLUTIONS', resolutions, selectControl
context._.each resolutions, (value, key, obj) ->
@logger.debug 'RRR', key, value
option = $('<option/>',
value: value
text: value)
selectControl.append option
if @resolution != null and @resolution != ''
selectControl.val(@resolution)

View File

@ -23,14 +23,16 @@
var STEP_SELECT_TRACKS = 2;
var STEP_SELECT_CHAT = 3;
var STEP_DIRECT_MONITOR = 4;
var STEP_ROUTER_NETWORK = 5;
var STEP_SUCCESS = 6;
var STEP_VIDEO_GEAR = 5;
var STEP_ROUTER_NETWORK = 6;
var STEP_SUCCESS = 7;
var stepUnderstandGear = new context.JK.StepUnderstandGear(app, this);
var stepSelectGear = new context.JK.StepSelectGear(app, this);
var stepConfigureTracks = new context.JK.StepConfigureTracks(app, this);
var stepConfigureVoiceChat = new context.JK.StepConfigureVoiceChat(app, this);
var stepDirectMonitoring = new context.JK.StepDirectMonitoring(app, this);
var stepVideoGear = new context.JK.StepVideoGear(app, this);
var stepNetworkTest = new context.JK.StepNetworkTest(app, this);
var stepSuccess = new context.JK.StepSuccess(app, this);
@ -39,9 +41,7 @@
1: stepSelectGear,
2: stepConfigureTracks,
3: stepConfigureVoiceChat,
4: stepDirectMonitoring,
5: stepNetworkTest,
6: stepSuccess
4: stepDirectMonitoring
}
function newSession() {
@ -206,7 +206,9 @@
$dialog = $('#gear-wizard-dialog');
$wizardSteps = $dialog.find('.wizard-step');
$templateSteps = $('#template-ftuesteps');
console.log("foo")
var videoGear = $wizardSteps.filter($('.video-gear'))
console.log("fooBAR")
wizard = new context.JK.Wizard(app);
stepUnderstandGear.initialize($wizardSteps.filter($('[layout-wizard-step=0]')), self);
@ -214,11 +216,21 @@
stepConfigureTracks.initialize($wizardSteps.filter($('[layout-wizard-step=2]')), self);
stepConfigureVoiceChat.initialize($wizardSteps.filter($('[layout-wizard-step=3]')), self);
stepDirectMonitoring.initialize($wizardSteps.filter($('[layout-wizard-step=4]')), self);
stepNetworkTest.initialize($wizardSteps.filter($('[layout-wizard-step=5]')), self);
stepSuccess.initialize($wizardSteps.filter($('[layout-wizard-step=6]')), self);
stepNetworkTest.initialize($wizardSteps.filter($('.network-test')), self);
stepSuccess.initialize($wizardSteps.filter($('.success')), self);
console.log("videoGear", videoGear)
if(videoGear.length) {
stepVideoGear.initialize(videoGear, self);
STEPS[5]=stepVideoGear
STEPS[6]=stepNetworkTest
STEPS[7]=stepSuccess
} else {
STEPS[5]=stepNetworkTest
STEPS[6]=stepSuccess
}
wizard.initialize($dialog, $wizardSteps, STEPS);
events();
}

View File

@ -0,0 +1,28 @@
(function (context, $) {
"use strict"
context.JK = context.JK || {}
context.JK.StepVideoGear = function (app, $dialog) {
var $step = null
var $webcamViewer = new context.JK.WebcamViewer()
function initialize(_$step) {
$step = _$step
$webcamViewer.init($step)
}
function beforeShow() {
$webcamViewer.beforeShow()
}
function beforeHide() {
$webcamViewer.setVideoOff()
}
this.beforeShow = beforeShow
this.beforeHide = beforeHide
this.initialize = initialize
return this
}
})(window, jQuery)

View File

@ -49,6 +49,22 @@
width: 20%;
}
.wizard_control {
margin-bottom: 10px;
}
.content-wrapper .account-video {
.subcaption {
margin-bottom: 4px;
}
}
.webcam-container {
margin-top: 10px;
}
.account-left h2 {
color: #FFFFFF;
font-size: 23px;
@ -107,7 +123,7 @@
}
}
.audio .audio-profiles-short{
.audio .audio-profiles-short, .video .video-profiles-short {
white-space: normal;
}
@ -151,7 +167,6 @@
}
.account-audio {
table.generaltable td {
vertical-align:middle;
}
@ -160,7 +175,6 @@
margin-bottom:9px;
}
.rescanning-notice {
display:none;
@ -216,7 +230,6 @@
}
}
.spinner-large {
width:300px;
height:300px;

View File

@ -170,8 +170,21 @@ a img {border:none;}
small, .small {font-size:11px;}
.bold {font-weight:bold;}
.button-grey-toggle.selected {
background-color: #999;
text-decoration:none;
&:hover {
background-color: #999;
color:#ccc;
text-decoration:none;
}
}
.button-grey {
.button-grey-toggle:hover {
text-decoration:none;
}
.button-grey, .button-grey-toggle {
margin:0px 8px 0px 8px;
background-color:#666;
border: solid 1px #868686;

View File

@ -315,7 +315,46 @@
}
}
.wizard-step[layout-wizard-step="5"], .network-test {
// Video Gear:
.wizard-step.video-gear {
.wizard-step-content .wizard-step-column {
&:nth-of-type(1) {
width: 50%;
height: 350px;
}
&:nth-of-type(2) {
width: 50%;
}
.webcam-preview {
.webcam-content {
min-width: 200px;
min-height: 200px;
}
width: auto;
height: auto;
overflow: scroll;
}
.wizard_control {
margin-bottom: 10px;
}
ul {
margin-bottom: 20px;
a {
color:$ColorLink;
}
a:hover {
color:$ColorLinkHover;
}
}
}
}
.wizard-step.network-test {
.wizard-step-content .wizard-step-column {
&:nth-of-type(1) {
@ -477,7 +516,7 @@
}
}
.wizard-step[layout-wizard-step="6"] {
.wizard-step.success {
.wizard-step-content .wizard-step-column {
&:nth-of-type(1) {
width: 50%;

View File

@ -50,9 +50,32 @@
<a id="account-edit-audio-link" href="#" class="button-orange">UPDATE</a>
</div>
<br clear="all" />
<hr />
{% } %}
<br clear="all" />
<hr />
<% if Rails.application.config.video_available || (current_user && current_user.admin) %>
<div class="account-left">
<h2>video gear:</h2>
</div>
<div class="account-mid video">
<strong>Webcam:</strong> {{data.webcamName}}<br />
</div>
<div class="right">
<a id="account-edit-video-link" href="#" class="button-orange">UPDATE</a>
</div>
<br clear="all" />
<hr />
{% } %}
<% end %>
<div class="account-left">
<h2>identity:</h2>

View File

@ -0,0 +1,37 @@
<!-- Account Summary Dialog -->
<div layout="screen" layout-id="account/video" class="screen secondary" id="account-video-profile">
<!-- header -->
<div class="content-head">
<!-- icon -->
<div class="content-icon">
<%= image_tag "content/icon_account.png", {:width => 27, :height => 20} %>
</div>
<!-- section head text -->
<h1>my account</h1>
<%= render "screen_navigation" %>
</div>
<!-- end header -->
<!-- profile scrolling area -->
<div class="content-body">
<div id="account-video-content-scroller" class="content-body-scroller account-content-scroller">
<!-- content wrapper -->
<div class="content-wrapper account-video">
<div class="video-header">
<h2 class="subcaption">video gear:</h2>
<div class="subcaption">
Select webcam to use for video in sessions. Verify that you see video from webcam in window to the right. Configure webcam settings if desired.
</div>
</div>
<div class="webcam-container">
<%= render 'webcam' %>
</div>
</div>
</div>
</div>
<!-- end content scrolling area -->
</div>

View File

@ -7,7 +7,7 @@
.content-body
#session-controls
a#session-resync.button-grey.resync.left
= image_tag "content/icon_resync.png", {:align => "texttop", :height => 14, :width => 12}
= image_tag "content/icon_resync.png", {:align => "texttop", :height => 12, :width => 12}
| RESYNC
a#session-settings-button.button-grey.left[layout-link="session-settings"]
= image_tag "content/icon_settings_sm.png", {:align => "texttop", :height => 12, :width => 12}
@ -15,6 +15,10 @@
a.button-grey.left[layout-link="share-dialog"]
= image_tag "content/icon_share.png", {:align => "texttop", :height => 12, :width => 12}
| SHARE
- if Rails.application.config.video_available || (current_user && current_user.admin)
a#session-webcam.button-grey-toggle.video.left
= image_tag "content/icon_cam.png", {:align => "texttop", :height => 12, :width => 12}
| VIDEO
.block
.label
| VOLUME:
@ -109,6 +113,9 @@
br[clear="all"]
.play-controls-holder
= render "play_controls"
.webcam-container.hidden
/ Webcam is actually in another window.
= render 'webcam'
= render "configureTrack"
= render "addTrack"
= render "addNewGear"

View File

@ -0,0 +1,11 @@
h2.sub-header Webcam
form.video
.webcam-select-container.wizard_control
select.w100
.webcam-resolution-select-container.wizard_control
select.w100
.configure-webcam.wizard_control
a.button-orange.webcam-test-btn Test Webcam
.configure-webcam.wizard_control
a.button-orange.webcam-settings-btn Webcam Settings
em.no-webcam-msg.hidden No webcam detected. If using an external webcam, please make sure it is plugged in to your computer.

View File

@ -15,7 +15,7 @@
<%= render "searchResults" %>
<%= render "faders" %>
<%= render "vu_meters" %>
<%= render "ftue" %>
<!--%= render "ftue" % No longer used-->
<%= render "jamServer" %>
<%= render "iconInstrumentSelect" %>
<%= render "muteSelect" %>
@ -54,6 +54,7 @@
<%= render "account_profile" %>
<%= render "account_profile_avatar" %>
<%= render "account_audio_profile" %>
<%= render "account_video_profile" %>
<%= render "account_sessions" %>
<%= render "account_jamtracks" %>
<%= render "account_session_detail" %>
@ -215,6 +216,9 @@
var accountAudioProfile = new JK.AccountAudioProfile(JK.app);
accountAudioProfile.initialize();
var accountVideoProfile = new JK.AccountVideoProfile(JK.app);
accountVideoProfile.initialize();
var accountPaymentHistoryScreen = new JK.AccountPaymentHistoryScreen(JK.app);
accountPaymentHistoryScreen.initialize();

View File

@ -157,13 +157,19 @@
%img{src:'assets/content/icon_playbutton.png', width:20, height:20, align:'top'}
%span.direct-monitoring-btn Play
-step=4
-if Rails.application.config.video_available || (current_user && current_user.admin)
.wizard-step.video-gear{ 'layout-wizard-step' => "#{step+=1}", 'dialog-title' => "Select Video Gear", 'dialog-purpose' => "SelectVideoGear" }
.ftuesteps
.clearall
= render :partial => '/clients/wizard/gear/video_gear'
.wizard-step.network-test{ 'layout-wizard-step' => "5", 'dialog-title' => "Test Router & Network", 'dialog-purpose' => "TestRouterNetwork" }
.wizard-step.network-test{ 'layout-wizard-step' => "#{step+=1}", 'dialog-title' => "Test Router & Network", 'dialog-purpose' => "TestRouterNetwork" }
.ftuesteps
.clearall
= render :partial => '/clients/network_test'
.wizard-step{ 'layout-wizard-step' => "6", 'dialog-title' => "Success!", 'dialog-purpose' => "Success" }
.wizard-step.success{ 'layout-wizard-step' => "#{step+=1}", 'dialog-title' => "Success!", 'dialog-purpose' => "Success" }
.ftuesteps
.clearall
.wizard-step-content
@ -207,9 +213,13 @@
.ftue-step-title Configure Voice Chat
%a.ftue-stepnumber{'data-step-number' => 4} 5
.ftue-step-title Turn Off Direct Monitoring
%a.ftue-stepnumber{'data-step-number' => 5} 6
-step = 4
-if Rails.application.config.video_available || (current_user && current_user.admin)
%a.ftue-stepnumber{'data-step-number' => step+=1}=step+1
.ftue-step-title Select Video Gear
%a.ftue-stepnumber{'data-step-number' => step+=1}=step+1
.ftue-step-title Test Router & Network
%a.ftue-stepnumber{'data-step-number' => 6} 7
%a.ftue-stepnumber{'data-step-number' => step+=1}=step+1
.ftue-step-title Success!

View File

@ -0,0 +1,20 @@
.help-text In this step, you will select your video gear. Please watch the video for best instructions.
.wizard-step-content
.wizard-step-column
%h2 Instructions
.ftue-box.instructions
%ul
%li Select webcam to use for video in sessions.
%li Verify that you see the video for the webcam in the window to the right.
%li Configure webcam settings if desired.
.center
%a.button-orange.watch-video{href:'https://www.youtube.com/watch?v=f7niycdWm7Y', rel:'external'} WATCH VIDEO
.wizard-step-column
=render(partial: '/clients/webcam')
.clearall
/ Webcam from client can't currently be embedded:
/ .wizard-step-column
/ %h2.video-header Preview
/ .webcam-preview.ftue-box
/ .webcam-content

View File

@ -23,16 +23,16 @@
.field.w100.left{:purpose => "description"}
%label{:for => "description"} Description:
%textarea#claim-recording-description.w100{:name => "description"}
- if Rails.application.config.jam_tracks_available
.field.left{:purpose => "save_video"}
%input{:checked => "checked", :name => "save_video", :type => "checkbox"}/
%label{:for => "save_video"} Save Video to Computer
.field.left{:purpose => "upload_to_youtube"}
%span
%input{:checked => "checked", :name => "upload_to_youtube", :type => "checkbox"}/
%label{:for => "upload_to_youtube"} Upload Video to YouTube
%span
= render(:partial => "shared/google_login")
- if Rails.application.config.video_available || (current_user && current_user.admin)
.field.left{:purpose => "save_video"}
%input{:checked => "checked", :name => "save_video", :type => "checkbox"}/
%label{:for => "save_video"} Save Video to Computer
.field.left{:purpose => "upload_to_youtube"}
%span
%input{:checked => "checked", :name => "upload_to_youtube", :type => "checkbox"}/
%label{:for => "upload_to_youtube"} Upload Video to YouTube
%span
= render(:partial => "shared/google_login")
.field.left{:purpose => "is_public"}
%input{:checked => "checked", :name => "is_public", :type => "checkbox"}/
%label{:for => "is_public"} Public Recording

View File

@ -1,26 +1,3 @@
-content_for :extra_js do
javascript:
// Check for google authorization using AJAX and show/hide the
// google login button / "signed in" label as appropriate:
$(window).on('focus', function() {
$.ajax({
type: "GET",
dataType: "json",
url: "/auth/has_google_auth"
}).success(function(data) {
if(data.has_google_auth) {
$("input.google_login_button").addClass("hidden")
$("span.signed_in_to_google").removeClass("hidden")
if (window._oauth_win) {
window._oauth_win.close()
}
} else {
$("span.signed_in_to_google").addClass("hidden")
$("input.google_login_button").removeClass("hidden")
}
})
});
-google_auth = (current_user.nil?) ? nil : !!JamRuby::UserAuthorization.google_auth(current_user).first
span.signed_in_to_google class=((!google_auth) ? "hidden" : "") ="(Signed in)"
input.google_login_button class=((google_auth) ? "hidden" : "") type='image' onclick='window._oauth_win = window.open("/auth/google_login", "_blank", "height=500,width=500,menubar=no,resizable=no,status=no");' src="/assets/google_signin.png" height="30px"
input.google_login_button class=((google_auth) ? "hidden" : "") type='image' src="/assets/google_signin.png" height="30px"

View File

@ -21,7 +21,10 @@
<!-- <li class="payments"><%= link_to "Payments", '/client#/account/payments' %></li> -->
<% if current_user && current_user.musician? %>
<% class_val = current_user.affiliate_partner.present? ? 'audio' : 'audio account-menu-group' %>
<li class="<%= class_val%>"><%= link_to "Audio Gear", '/client#/account/audio' %></li>
<li class="audio"><%= link_to "Audio Gear", '/client#/account/audio' %></li>
<% if Rails.application.config.video_available || (current_user && current_user.admin) %>
<li class="<%= class_val%>"><%= link_to "Video Gear", '/client#/account/video' %></li>
<% end %>
<% end %>
<% if current_user && current_user.affiliate_partner.present? %>
<li class="affiliate account-menu-group"><%= link_to "Affiliate Report", '/client#/account/affiliate' %></li>

View File

@ -326,5 +326,6 @@ if defined?(Bundler)
config.recurly_tax_estimate_jam_track_plan = 'jamtrack-acdc-backinblack'
config.minimal_curtain = false
config.video_available = false
end
end

View File

@ -91,4 +91,5 @@ SampleApp::Application.configure do
config.youtube_app_name = "JamKazamDev"
config.jam_tracks_available=true
config.minimal_curtain = true
config.video_available=false
end

View File

@ -105,5 +105,6 @@ SampleApp::Application.configure do
config.recurly_subdomain = 'jamkazam-test'
config.log_level = :debug
config.jam_tracks_available = true
config.video_available = true
end

View File

@ -27,12 +27,10 @@ namespace :jam_tracks do
end
task sync_all: :environment do |task, args|
JamTrackImporter.synchronize_all(skip_audio_upload:false)
end
task sync_all_dev: :environment do |task, args|
JamTrackImporter.synchronize_all(skip_audio_upload:true)
end
@ -62,7 +60,6 @@ namespace :jam_tracks do
end
end
task sync_duration_all: :environment do |task, args|
importer = JamTrackImporter.synchronize_durations
end

View File

@ -8,14 +8,69 @@ describe "Gear Wizard", :js => true, :type => :feature, :capybara_feature => tru
before(:each) do
LatencyTester.delete_all
end
before(:all) do
@old_video_available=Rails.application.config.video_available
Rails.application.config.video_available=false
end
after(:all) do
Rails.application.config.video_available=@old_video_available
end
it "success path" do
FactoryGirl.create(:latency_tester)
fast_signin user, '/client#/account/audio'
find("div.account-audio a[data-purpose='add-profile']").trigger(:click)
walk_gear_wizard
# step 1 - intro
find('.btn-next').trigger(:click)
# step 2 - select gear
find('.ftue-step-title', text: 'Select & Test Audio Gear')
should_not have_selector('.resync-status') # when you enter this step,
jk_select('Built-in', 'div[layout-wizard-step="1"] select.select-audio-input-device')
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 3 - configure tracks
find('.ftue-step-title', text: 'Configure Tracks')
# drag one input over to tracks area http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#drag_to-instance_method
input = first('.ftue-input')
track_slot = first('.track-target')
input.drag_to(track_slot)
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 4 - configure voice chat
find('.ftue-step-title', text: 'Configure Voice Chat')
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 5 - configure direct monitoring
find('.ftue-step-title', text: 'Turn Off Direct Monitoring')
# make a diversion into the 'adjust gear speed' dialog
find('.adjust-settings-direct-monitor').trigger(:click)
# should see dialog header
find('h1', text: 'Adjust Gear Speed')
# change to 'moderate' speed
find('.speed-option.setting-fair ins').trigger(:click)
# should cause a spinner/io test, and then save button comes up as clickable
find('.btnSave.button-orange:not(.disabled)').trigger(:click)
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 6 - Test Router & Network
find('.ftue-step-title', text: 'Test Router & Network')
find('.button-orange.start-network-test').trigger(:click)
find('.user-btn', text: 'RUN NETWORK TEST ANYWAY').trigger(:click)
find('.button-orange.start-network-test')
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 7 - Success
find('.ftue-step-title', text: 'Success!')
find('.btn-close.button-orange').trigger(:click)
# should see prompt afterwards about joining a test session
find('h1', text: 'join test session')

View File

@ -125,53 +125,3 @@ def close_websocket
page.evaluate_script("window.JK.JamServer.close(true)")
end
# does not launch it; expects that to have just been done
def walk_gear_wizard
# step 1 - intro
find('.btn-next').trigger(:click)
# step 2 - select gear
find('.ftue-step-title', text: 'Select & Test Audio Gear')
should_not have_selector('.resync-status') # when you enter this step,
jk_select('Built-in', 'div[layout-wizard-step="1"] select.select-audio-input-device')
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 3 - configure tracks
find('.ftue-step-title', text: 'Configure Tracks')
# drag one input over to tracks area http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#drag_to-instance_method
input = first('.ftue-input')
track_slot = first('.track-target')
input.drag_to(track_slot)
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 4 - configure voice chat
find('.ftue-step-title', text: 'Configure Voice Chat')
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 5 - configure direct monitoring
find('.ftue-step-title', text: 'Turn Off Direct Monitoring')
# make a diversion into the 'adjust gear speed' dialog
find('.adjust-settings-direct-monitor').trigger(:click)
# should see dialog header
find('h1', text: 'Adjust Gear Speed')
# change to 'moderate' speed
find('.speed-option.setting-fair ins').trigger(:click)
# should cause a spinner/io test, and then save button comes up as clickable
find('.btnSave.button-orange:not(.disabled)').trigger(:click)
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 6 - Test Router & Network
find('.ftue-step-title', text: 'Test Router & Network')
find('.button-orange.start-network-test').trigger(:click)
find('.user-btn', text: 'RUN NETWORK TEST ANYWAY').trigger(:click)
find('.button-orange.start-network-test')
find('.btn-next.button-orange:not(.disabled)').trigger(:click)
# step 7 - Success
find('.ftue-step-title', text: 'Success!')
find('.btn-close.button-orange').trigger(:click)
end