Merge branch 'develop' of bitbucket.org:jamkazam/jam-cloud into develop

This commit is contained in:
Seth Call 2015-04-22 09:45:08 -05:00
commit a3021479fd
32 changed files with 667 additions and 180 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

View File

@ -39,6 +39,10 @@ describe JamTrack do
end
describe "artist_index" do
before :each do
JamTrack.delete_all
end
it "empty query" do
query, pager = JamTrack.artist_index({}, user)
query.size.should == 0
@ -172,5 +176,4 @@ describe JamTrack do
end
end
end
end
end

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,14 @@
var invalidProfiles = prettyPrintAudioProfiles(context.JK.getBadConfigMap());
var sessionSummary = summarizeSession(userDetail);
var webcamName;
var webcam = context.jamClient.FTUECurrentSelectedVideoDevice()
if (webcam==null || typeof(webcam)=="undefined" || Object.keys(webcam).length==0) {
webcamName = "None Configured"
} else {
webcamName = _.values(webcam)[0]
}
var $template = $(context._.template($('#template-account-main').html(), {
email: userDetail.email,
name: userDetail.name,
@ -56,6 +66,7 @@
invalidProfiles : invalidProfiles,
isNativeClient: gon.isNativeClient,
musician: context.JK.currentUserMusician,
webcamName: webcamName,
sales_count: userDetail.sales_count
} , { variable: 'data' }));
@ -65,8 +76,9 @@
$('#account-scheduled-sessions-link').show();
} else {
$('#account-scheduled-sessions-link').hide();
}
}
}
}// function
function prettyPrintAudioProfiles(profileMap) {
var profiles = "";
@ -110,6 +122,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 +171,11 @@
window.location = "/client#/account/audio"
}
function navToEditVideo() {
resetForm()
window.location = "/client#/account/video"
}
function navToPaymentHistory() {
window.location = '/client#/account/paymentHistory'
}
@ -178,6 +196,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
@ -721,7 +723,7 @@
function _initDialogs() {
configureTrackDialog.initialize();
addNewGearDialog.initialize();
addNewGearDialog.initialize();
}
// Get the latest list of underlying audio mixer channels, and populates:
@ -2018,15 +2020,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';
@ -2486,6 +2485,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() {
@ -2746,7 +2757,6 @@
}// function
function openBackingTrackFile(e) {
// just ignore the click if they are currently recording for now
if(sessionModel.recordingModel.isRecording()) {
app.notify({
@ -3097,7 +3107,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);
}
@ -3130,6 +3139,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);
@ -3213,7 +3223,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,114 @@
$ = 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) =>
@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)
@toggleBtn.on 'click', @toggleWebcam
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) =>
device = @webcamSelect.val()
if device?
caps = @client.FTUEGetVideoCaptureDeviceCapabilities(device)
@logger.debug("Got capabilities from device", caps, device)
@client.FTUESelectVideoCaptureDevice(device, caps)
selectResolution:() =>
@logger.debug 'Selecting res control: ', @resolutionSelect
@resolution = @resolutionSelect.val()
if @resolution?
@logger.debug 'Selecting res: ', @resolution
@client.FTUESetVideoEncodeResolution @resolution
if @isVideoShared
this.setVideoOff()
this.toggleWebcam()
setVideoOff:() =>
if this.isVideoShared()
@client.SessStopVideoSharing()
isVideoShared:() =>
@videoShared
setToggleState:() =>
available = @webcamSelect.find('option').size() > 0
shared = this.isVideoShared()
@toggleBtn.prop 'disabled', true
@toggleBtn.prop 'disabled', !available
toggleWebcam:() =>
@logger.debug 'Toggling webcam from: ', this.isVideoShared()
if this.isVideoShared()
@toggleBtn.removeClass("selected")
@client.SessStopVideoSharing()
@videoShared = false
else
@toggleBtn.addClass("selected")
@client.SessStartVideoSharing 0
@videoShared = true
selectedDeviceName:() =>
webcamName="None Configured"
webcam = @client.FTUECurrentSelectedVideoDevice()
if (webcam? && Object.keys(webcam).length>0)
webcamName = _.values(webcam)[0]
webcamName
loadWebCams:() =>
devices = @client.FTUEGetVideoCaptureDeviceNames()
selectedDevice = this.selectedDeviceName()
selectControl = @webcamSelect
context._.each devices, (device) ->
selected = device == selectedDevice
option = $('<option/>',
id: device
value: device
text: device)
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) ->
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

@ -38,22 +38,40 @@
<hr/>
{% if (data.isNativeClient) { %}
<div class="account-left">
<h2>audio gear:</h2>
</div>
<div class="account-left">
<h2>audio gear:</h2>
</div>
<div class="account-mid audio">
<strong>Profiles:</strong> <span class="audio-profiles-short">{{data.validProfiles}}</span>
</div>
<div class="account-mid audio">
<strong>Profiles:</strong> <span class="audio-profiles-short">{{data.validProfiles}}</span>
</div>
<div class="right">
<a id="account-edit-audio-link" href="#" class="button-orange">UPDATE</a>
</div>
<br clear="all" />
<div class="right">
<a id="account-edit-audio-link" href="#" class="button-orange">UPDATE</a>
</div>
<br clear="all" />
<hr />
<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>
</div>

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 the external application window (it may be behind this window). 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-grey-toggle.webcam-test-btn Test Webcam
.configure-webcam.wizard_control
a.button-grey-toggle.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