wip
This commit is contained in:
parent
ebe1278e5e
commit
05666f7927
|
|
@ -159,3 +159,4 @@ update_get_work_for_larger_radius.sql
|
|||
periodic_emails.sql
|
||||
remember_extra_scoring_data.sql
|
||||
indexing_for_regions.sql
|
||||
latency_tester.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE latency_testers (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
client_id VARCHAR(64) UNIQUE NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE connections ALTER COLUMN user_id DROP NOT NULL;
|
||||
|
|
@ -56,6 +56,7 @@ group :test do
|
|||
gem 'faker'
|
||||
gem 'resque_spec' #, :path => "/home/jam/src/resque_spec/"
|
||||
gem 'timecop'
|
||||
gem 'rspec-prof'
|
||||
end
|
||||
|
||||
# Specify your gem's dependencies in jam_ruby.gemspec
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ require "jam_ruby/models/band_invitation"
|
|||
require "jam_ruby/models/band_musician"
|
||||
require "jam_ruby/models/connection"
|
||||
require "jam_ruby/models/diagnostic"
|
||||
require "jam_ruby/models/latency_tester"
|
||||
require "jam_ruby/models/friendship"
|
||||
require "jam_ruby/models/active_music_session"
|
||||
require "jam_ruby/models/music_session_comment"
|
||||
|
|
|
|||
|
|
@ -153,11 +153,11 @@ SQL
|
|||
# NOTE this is only used for testing purposes;
|
||||
# actual deletes will be processed in the websocket context which cleans up dependencies
|
||||
def expire_stale_connections()
|
||||
self.stale_connection_client_ids().each { |client| self.delete_connection(client[:client_id]) }
|
||||
self.stale_connection_client_ids.each { |client| self.delete_connection(client[:client_id]) }
|
||||
end
|
||||
|
||||
# expiring connections in stale state, which deletes them
|
||||
def stale_connection_client_ids()
|
||||
def stale_connection_client_ids
|
||||
clients = []
|
||||
ConnectionManager.active_record_transaction do |connection_manager|
|
||||
conn = connection_manager.pg_conn
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module ValidationMessages
|
|||
INVALID_FPFILE = "is not valid"
|
||||
|
||||
#connection
|
||||
|
||||
USER_OR_LATENCY_TESTER_PRESENT = "user or latency_tester must be present"
|
||||
SELECT_AT_LEAST_ONE = "Please select at least one track" # DO NOT CHANGE THIS TEXT MESSAGE UNLESS YOU CHANGE createSession.js.erb, which is looking for it
|
||||
FAN_CAN_NOT_JOIN_AS_MUSICIAN = "A fan can not join a music session as a musician"
|
||||
MUSIC_SESSION_MUST_BE_SPECIFIED = "A music session must be specified"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ module JamRuby
|
|||
# client_types
|
||||
TYPE_CLIENT = 'client'
|
||||
TYPE_BROWSER = 'browser'
|
||||
TYPE_LATENCY_TESTER = 'latency_tester'
|
||||
|
||||
attr_accessor :joining_session
|
||||
|
||||
|
|
@ -13,11 +14,14 @@ module JamRuby
|
|||
|
||||
belongs_to :user, :class_name => "JamRuby::User"
|
||||
belongs_to :music_session, :class_name => "JamRuby::ActiveMusicSession", foreign_key: :music_session_id
|
||||
has_one :latency_tester, class_name: 'JamRuby::LatencyTester', foreign_key: :client_id, primary_key: :client_id
|
||||
has_many :tracks, :class_name => "JamRuby::Track", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all
|
||||
|
||||
validates :as_musician, :inclusion => {:in => [true, false]}
|
||||
validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER]}
|
||||
validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER, TYPE_LATENCY_TESTER]}
|
||||
validate :can_join_music_session, :if => :joining_session?
|
||||
validate :user_or_latency_tester_present
|
||||
|
||||
after_save :require_at_least_one_track_when_in_session, :if => :joining_session?
|
||||
after_create :did_create
|
||||
after_save :report_add_participant
|
||||
|
|
@ -190,5 +194,11 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def user_or_latency_tester_present
|
||||
if user.nil? && client_type != TYPE_LATENCY_TESTER
|
||||
errors.add(:connection, ValidationMessages::USER_OR_LATENCY_TESTER_PRESENT)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
module JamRuby
|
||||
class LatencyTester < ActiveRecord::Base
|
||||
|
||||
belongs_to :connection, class_name: 'JamRuby::Connection', foreign_key: :client_id, primary_key: :client_id
|
||||
|
||||
|
||||
# we need to find that latency_tester with the specified connection (and reconnect it)
|
||||
# or bootstrap a new latency_tester
|
||||
def self.connect(options)
|
||||
client_id = options[:client_id]
|
||||
ip_address = options[:ip_address]
|
||||
connection_stale_time = options[:connection_stale_time]
|
||||
connection_expire_time = options[:connection_expire_time]
|
||||
# first try to find a LatencyTester with that client_id
|
||||
latency_tester = LatencyTester.find_by_client_id(client_id)
|
||||
|
||||
if latency_tester
|
||||
if latency_tester.connection
|
||||
connection = latency_tester.connection
|
||||
else
|
||||
connection = Connection.new
|
||||
connection.client_id = client_id
|
||||
latency_tester.connection = connection
|
||||
end
|
||||
else
|
||||
latency_tester = LatencyTester.new
|
||||
unless latency_tester.save
|
||||
return latency_tester
|
||||
end
|
||||
connection = Connection.new
|
||||
connection.latency_tester = latency_tester
|
||||
connection.client_id = client_id
|
||||
end
|
||||
|
||||
if ip_address and !ip_address.eql?(connection.ip_address)
|
||||
# locidispid stuff
|
||||
addr = JamIsp.ip_to_num(ip_address)
|
||||
isp = JamIsp.lookup(addr)
|
||||
if isp.nil? then ispid = 0 else ispid = isp.coid end
|
||||
block = GeoIpBlocks.lookup(addr)
|
||||
if block.nil? then locid = 0 else locid = block.locid end
|
||||
location = GeoIpLocations.lookup(locid)
|
||||
if location.nil?
|
||||
# todo what's a better default location?
|
||||
locidispid = 0
|
||||
else
|
||||
locidispid = locid*1000000+ispid
|
||||
end
|
||||
|
||||
connection.ip_address = ip_address
|
||||
connection.addr = addr
|
||||
connection.locidispid = locidispid
|
||||
end
|
||||
|
||||
connection.client_type = 'latency_tester'
|
||||
connection.aasm_state = Connection::CONNECT_STATE.to_s
|
||||
connection.stale_time = connection_stale_time
|
||||
connection.expire_time = connection_expire_time
|
||||
connection.as_musician = false
|
||||
unless connection.save
|
||||
return connection
|
||||
end
|
||||
|
||||
return latency_tester
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -112,6 +112,7 @@ FactoryGirl.define do
|
|||
addr 0
|
||||
locidispid 0
|
||||
client_type 'client'
|
||||
association :user, factory: :user
|
||||
end
|
||||
|
||||
factory :invitation, :class => JamRuby::Invitation do
|
||||
|
|
@ -464,4 +465,8 @@ FactoryGirl.define do
|
|||
creator JamRuby::Diagnostic::CLIENT
|
||||
data Faker::Lorem.sentence
|
||||
end
|
||||
|
||||
factory :latency_tester, :class => JamRuby::LatencyTester do
|
||||
association :connection
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe LatencyTester do
|
||||
|
||||
let(:params) {{client_id: 'abc', ip_address: '10.1.1.1', connection_stale_time:40, connection_expire_time:60} }
|
||||
|
||||
it "success" do
|
||||
latency_tester = FactoryGirl.create(:latency_tester)
|
||||
latency_tester.connection.should_not be_nil
|
||||
latency_tester.connection.latency_tester.should_not be_nil
|
||||
|
||||
end
|
||||
|
||||
describe "connect" do
|
||||
it "no existing latency tester" do
|
||||
latency_tester = LatencyTester.connect(params)
|
||||
latency_tester.errors.any?.should be_false
|
||||
latency_tester.connection.ip_address.should == params[:ip_address]
|
||||
latency_tester.connection.stale_time.should == params[:connection_stale_time]
|
||||
latency_tester.connection.expire_time.should == params[:connection_expire_time]
|
||||
end
|
||||
|
||||
it "existing latency tester, no connection" do
|
||||
latency_tester = FactoryGirl.create(:latency_tester, connection: nil)
|
||||
latency_tester.connection.should be_nil
|
||||
|
||||
latency_tester.client_id = params[:client_id ]
|
||||
latency_tester.save!
|
||||
|
||||
found = LatencyTester.connect(params)
|
||||
found.should == latency_tester
|
||||
found.connection.should_not be_nil
|
||||
found.connection.aasm_state.should == Connection::CONNECT_STATE.to_s
|
||||
found.connection.client_id.should == latency_tester.client_id
|
||||
end
|
||||
|
||||
it "existing latency tester, existing connection" do
|
||||
latency_tester = FactoryGirl.create(:latency_tester)
|
||||
|
||||
latency_tester.connection.aasm_state = Connection::STALE_STATE.to_s
|
||||
latency_tester.save!
|
||||
set_updated_at(latency_tester.connection, 1.days.ago)
|
||||
|
||||
params[:client_id] = latency_tester.connection.client_id
|
||||
|
||||
found = LatencyTester.connect(params)
|
||||
found.should == latency_tester
|
||||
found.connection.should == latency_tester.connection
|
||||
# state should have refreshed from stale to connected
|
||||
found.connection.aasm_state.should == Connection::CONNECT_STATE.to_s
|
||||
# updated_at needs to be poked on connection to keep stale non-stale
|
||||
(found.connection.updated_at - latency_tester.connection.updated_at).to_i.should == 60 * 60 * 24 # 1 day
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,13 @@ class SpecDb
|
|||
def self.recreate_database
|
||||
conn = PG::Connection.open("dbname=postgres user=postgres password=postgres host=localhost")
|
||||
conn.exec("DROP DATABASE IF EXISTS #{TEST_DB_NAME}")
|
||||
conn.exec("CREATE DATABASE #{TEST_DB_NAME}")
|
||||
if ENV['TABLESPACE']
|
||||
conn.exec("CREATE DATABASE #{TEST_DB_NAME} WITH TABLESPACE=#{ENV['TABLESPACE']}")
|
||||
else
|
||||
conn.exec("CREATE DATABASE #{TEST_DB_NAME}")
|
||||
end
|
||||
|
||||
|
||||
JamDb::Migrator.new.migrate(:dbname => TEST_DB_NAME, :user => "postgres", :password => "postgres", :host => "localhost")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ ENV["RAILS_ENV"] = "test"
|
|||
|
||||
require 'simplecov'
|
||||
require 'support/utilities'
|
||||
require 'support/profile'
|
||||
require 'active_record'
|
||||
require 'jam_db'
|
||||
require 'spec_db'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
if ENV['PROFILE']
|
||||
require 'ruby-prof'
|
||||
RSpec.configure do |c|
|
||||
def profile
|
||||
result = RubyProf.profile { yield }
|
||||
name = example.metadata[:full_description].downcase.gsub(/[^a-z0-9_-]/, "-").gsub(/-+/, "-")
|
||||
printer = RubyProf::CallTreePrinter.new(result)
|
||||
Dir.mkdir('tmp/performance')
|
||||
open("tmp/performance/callgrind.#{name}.#{Time.now.to_i}.trace", "w") do |f|
|
||||
printer.print(f)
|
||||
end
|
||||
end
|
||||
|
||||
c.around(:each) do |example|
|
||||
if ENV['PROFILE'] == 'all' or (example.metadata[:profile] and ENV['PROFILE'])
|
||||
profile { example.run }
|
||||
else
|
||||
example.run
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -9,7 +9,8 @@
|
|||
var $dialog = null;
|
||||
var $wizardSteps = null;
|
||||
var $currentWizardStep = null;
|
||||
var step = 0;
|
||||
var step = null;
|
||||
var previousStep = null;
|
||||
var $templateSteps = null;
|
||||
var $templateButtons = null;
|
||||
var $templateAudioPort = null;
|
||||
|
|
@ -48,11 +49,21 @@
|
|||
6: stepSuccess
|
||||
}
|
||||
|
||||
function beforeHideStep($step) {
|
||||
var stepInfo = STEPS[step];
|
||||
function newSession() {
|
||||
context._.each(STEPS, function(stepInfo, stepNumber) {
|
||||
if(stepInfo.newSession) {
|
||||
stepInfo.newSession.call(stepInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function beforeHideStep() {
|
||||
if(!previousStep) {return}
|
||||
|
||||
var stepInfo = STEPS[previousStep];
|
||||
|
||||
if (!stepInfo) {
|
||||
throw "unknown step: " + step;
|
||||
throw "unknown step: " + previousStep;
|
||||
}
|
||||
|
||||
if(stepInfo.beforeHide) {
|
||||
|
|
@ -73,7 +84,7 @@
|
|||
function moveToStep() {
|
||||
var $nextWizardStep = $wizardSteps.filter($('[layout-wizard-step=' + step + ']'));
|
||||
|
||||
beforeHideStep($currentWizardStep);
|
||||
beforeHideStep();
|
||||
|
||||
$wizardSteps.hide();
|
||||
|
||||
|
|
@ -141,6 +152,7 @@
|
|||
var newProfileName = 'FTUEAttempt-' + new Date().getTime().toString();
|
||||
logger.debug("setting FTUE-prefixed profile name to: " + newProfileName);
|
||||
context.jamClient.FTUESetMusicProfileName(newProfileName);
|
||||
newSession();
|
||||
}
|
||||
|
||||
var profileName = context.jamClient.FTUEGetMusicProfileName();
|
||||
|
|
@ -150,6 +162,8 @@
|
|||
}
|
||||
|
||||
function beforeShow(args) {
|
||||
previousStep = null;
|
||||
|
||||
context.jamClient.FTUECancel();
|
||||
context.jamClient.FTUESetStatus(false);
|
||||
findOrCreateFTUEProfile();
|
||||
|
|
@ -157,7 +171,7 @@
|
|||
step = args.d1;
|
||||
if (!step) step = 0;
|
||||
step = parseInt(step);
|
||||
moveToStep();
|
||||
moveToStep(null);
|
||||
}
|
||||
|
||||
function afterShow() {
|
||||
|
|
@ -165,12 +179,14 @@
|
|||
}
|
||||
|
||||
function afterHide() {
|
||||
step = null;
|
||||
context.jamClient.FTUESetStatus(true);
|
||||
context.jamClient.FTUECancel();
|
||||
}
|
||||
|
||||
function back() {
|
||||
if ($(this).is('.button-grey')) return false;
|
||||
previousStep = step;
|
||||
step = step - 1;
|
||||
moveToStep();
|
||||
return false;
|
||||
|
|
@ -185,6 +201,7 @@
|
|||
if(!result) {return false;}
|
||||
}
|
||||
|
||||
previousStep = step;
|
||||
step = step + 1;
|
||||
|
||||
moveToStep();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
var $instrumentsHolder = null;
|
||||
|
||||
|
||||
|
||||
function loadChannels() {
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
|
||||
|
|
@ -100,7 +99,7 @@
|
|||
if(track.channels.length > 0) {
|
||||
tracks.tracks.push(track);
|
||||
}
|
||||
var $instrument = $instrumentsHolder.find('.icon-instrument-select[data-num="' + index + '"]');
|
||||
var $instrument = $instrumentsHolder.find('[data-num="' + index + '"]').find('.icon-instrument-select');
|
||||
track.instrument_id = $instrument.data('instrument_id');
|
||||
})
|
||||
return tracks;
|
||||
|
|
@ -140,10 +139,36 @@
|
|||
context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
|
||||
|
||||
});
|
||||
context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id);
|
||||
logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", trackNumber, track.instrument_id);
|
||||
context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
|
||||
});
|
||||
|
||||
context.jamClient.TrackSaveAssignments();
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function loadTrackInstruments() {
|
||||
var $trackInstruments = $instrumentsHolder.find('.track-instrument');
|
||||
|
||||
context._.each($trackInstruments, function(trackInstrument) {
|
||||
var $trackInstrument = $(trackInstrument);
|
||||
|
||||
var trackIndex = parseInt($trackInstrument.attr('data-num')) + 1;
|
||||
|
||||
var clientInstrument = context.jamClient.TrackGetInstrument(trackIndex);
|
||||
|
||||
var instrument = context.JK.client_to_server_instrument_map[clientInstrument];
|
||||
|
||||
$trackInstrument.instrumentSelectorSet(instrument ? instrument.server_id : instrument);
|
||||
});
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
|
|
@ -153,13 +178,12 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
save(tracks);
|
||||
|
||||
return true;
|
||||
return save(tracks);
|
||||
}
|
||||
|
||||
function beforeShow() {
|
||||
loadChannels();
|
||||
loadTrackInstruments();
|
||||
}
|
||||
|
||||
function unassignChannel($channel) {
|
||||
|
|
@ -210,9 +234,9 @@
|
|||
function initializeInstrumentDropdown() {
|
||||
var i;
|
||||
for(i = 0; i < MAX_TRACKS; i++) {
|
||||
var $instrumentSelect = context.JK.iconInstrumentSelect();
|
||||
$instrumentSelect.attr('data-num', i);
|
||||
$instrumentsHolder.append($instrumentSelect);
|
||||
var $root = $('<div class="track-instrument"></div>');
|
||||
$root.instrumentSelector().attr('data-num', i);
|
||||
$instrumentsHolder.append($root);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,143 @@
|
|||
context.JK = context.JK || {};
|
||||
context.JK.StepConfigureVoiceChat = function (app) {
|
||||
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
|
||||
var $step = null;
|
||||
var $reuseAudioInputRadio = null;
|
||||
var $useChatInputRadio = null;
|
||||
var $chatInputs = null;
|
||||
var $templateChatInput = null;
|
||||
|
||||
function newSession() {
|
||||
$reuseAudioInputRadio.attr('checked', 'checked').iCheck('check');
|
||||
}
|
||||
|
||||
function isChannelAvailableForChat(chatChannelId, musicPorts) {
|
||||
var result = true;
|
||||
context._.each(musicPorts.input, function(inputChannel) {
|
||||
// if the channel is currently assigned to a track, it not unassigned
|
||||
if(inputChannel.id == chatChannelId && (inputChannel.assignment > 0)) {
|
||||
result = false;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isChatEnabled() {
|
||||
return $useChatInputRadio.is(':checked');
|
||||
}
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
if(isChatEnabled()) {
|
||||
enableChat();
|
||||
}
|
||||
else {
|
||||
disableChat();
|
||||
}
|
||||
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
var chatInputs = context.jamClient.FTUEGetChatInputs();
|
||||
|
||||
$chatInputs.empty();
|
||||
|
||||
context._.each(chatInputs, function(chatChannelName, chatChannelId) {
|
||||
if(isChannelAvailableForChat(chatChannelId, musicPorts)) {
|
||||
var $chat = $(context._.template($templateChatInput.html(), {id: chatChannelId, name: chatChannelName}, { variable: 'data' }));
|
||||
$chat.hide(); // we'll show it once it's styled with iCheck
|
||||
$chatInputs.append($chat);
|
||||
}
|
||||
});
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
context.JK.checkbox($radioButtons).on('iChecked', function(e) {
|
||||
var $input = $(e.currentTarget);
|
||||
var channelId = $input.attr('data-channel-id');
|
||||
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.CHAT);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if(!isChatEnabled()) {
|
||||
$radioButtons.iCheck('disable');
|
||||
}
|
||||
|
||||
$chatInputs.find('.chat-input').show().on('click', function() {
|
||||
if(!isChatEnabled()) {
|
||||
context.JK.prodBubble($step.find('.use-chat-input h3'), 'chat-not-enabled', {}, { positions:['left']});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function disableChat() {
|
||||
logger.debug("FTUE: disabling chat");
|
||||
context.jamClient.TrackSetChatEnable(false);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to disable chat. ' + result);
|
||||
return false;
|
||||
}
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
$radioButtons.iCheck('disable');
|
||||
}
|
||||
|
||||
function enableChat() {
|
||||
logger.debug("FTUE: enabling chat");
|
||||
context.jamClient.TrackSetChatEnable(true);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to enable chat. ' + result);
|
||||
return false;
|
||||
}
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
$radioButtons.iCheck('enable');
|
||||
}
|
||||
|
||||
function handleChatEnabledToggle() {
|
||||
context.JK.checkbox($reuseAudioInputRadio);
|
||||
context.JK.checkbox($useChatInputRadio);
|
||||
|
||||
// plugin sets to relative on the element; have to do this as an override
|
||||
$reuseAudioInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
||||
$useChatInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
||||
|
||||
$reuseAudioInputRadio.on('ifChecked', disableChat);
|
||||
$useChatInputRadio.on('ifChecked', enableChat)
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
|
||||
$reuseAudioInputRadio = $step.find('.reuse-audio-input input');
|
||||
$useChatInputRadio = $step.find('.use-chat-input input');
|
||||
$chatInputs = $step.find('.chat-inputs');
|
||||
$templateChatInput = $('#template-chat-input');
|
||||
|
||||
handleChatEnabledToggle();
|
||||
}
|
||||
|
||||
this.newSession = newSession;
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
|
|
|
|||
|
|
@ -181,11 +181,23 @@
|
|||
}
|
||||
|
||||
function selectedBufferIn() {
|
||||
return parseFloat($frameSize.val());
|
||||
return parseFloat($bufferIn.val());
|
||||
}
|
||||
|
||||
function selectedBufferOut() {
|
||||
return parseFloat($frameSize.val());
|
||||
return parseFloat($bufferOut.val());
|
||||
}
|
||||
|
||||
function setFramesize(value) {
|
||||
$frameSize.val(value);
|
||||
}
|
||||
|
||||
function setBufferIn(value) {
|
||||
$bufferIn.val(value)
|
||||
}
|
||||
|
||||
function setBufferOut(value) {
|
||||
$bufferOut.val(value)
|
||||
}
|
||||
|
||||
function initializeNextButtonState() {
|
||||
|
|
@ -633,15 +645,16 @@
|
|||
|
||||
function initializeASIOButtons() {
|
||||
$asioInputControlBtn.unbind('click').click(function () {
|
||||
context.jamClient.FTUEOpenControlPanel(); // TODO: supply with ID when VRFS-1707 is done
|
||||
context.jamClient.FTUEOpenControlPanel(selectedAudioInput());
|
||||
});
|
||||
$asioOutputControlBtn.unbind('click').click(function () {
|
||||
context.jamClient.FTUEOpenControlPanel(); // TODO: supply with ID when VRFS-1707 is done
|
||||
context.jamClient.FTUEOpenControlPanel(selectedAudioOutput());
|
||||
});
|
||||
}
|
||||
|
||||
function initializeKnobs() {
|
||||
$frameSize.unbind('change').change(function () {
|
||||
updateDefaultBuffers();
|
||||
jamClient.FTUESetFrameSize(selectedFramesize());
|
||||
});
|
||||
|
||||
|
|
@ -841,6 +854,46 @@
|
|||
else {
|
||||
$resyncBtn.css('visibility', 'hidden');
|
||||
}
|
||||
|
||||
updateDefaultFrameSize();
|
||||
|
||||
updateDefaultBuffers();
|
||||
}
|
||||
|
||||
function updateDefaultFrameSize() {
|
||||
if(selectedDeviceInfo.input.type == 'Win32_wdm' || selectedDeviceInfo.output.type == 'Win32_wdm') {
|
||||
setFramesize('10');
|
||||
}
|
||||
|
||||
jamClient.FTUESetFrameSize(selectedFramesize());
|
||||
}
|
||||
|
||||
function updateDefaultBuffers() {
|
||||
|
||||
// handle specific framesize settings
|
||||
if(selectedDeviceInfo.input.type == 'Win32_wdm' || selectedDeviceInfo.output.type == 'Win32_wdm') {
|
||||
var framesize = selectedFramesize();
|
||||
|
||||
if(framesize == 2.5) {
|
||||
setBufferIn('1');
|
||||
setBufferOut('1');
|
||||
}
|
||||
else if(framesize == 5) {
|
||||
setBufferIn('3');
|
||||
setBufferOut('2');
|
||||
}
|
||||
else {
|
||||
setBufferIn('6');
|
||||
setBufferOut('5');
|
||||
}
|
||||
}
|
||||
else {
|
||||
setBufferIn(0);
|
||||
setBufferOut(0);
|
||||
}
|
||||
|
||||
jamClient.FTUESetInputLatency(selectedBufferIn());
|
||||
jamClient.FTUESetOutputLatency(selectedBufferOut());
|
||||
}
|
||||
|
||||
function processIOScore(io) {
|
||||
|
|
@ -932,15 +985,22 @@
|
|||
else {
|
||||
renderIOScore(null, null, null, 'starting', 'starting', 'starting');
|
||||
var testTimeSeconds = gon.ftue_io_wait_time; // allow time for IO to establish itself
|
||||
context.jamClient.FTUEStartIoPerfTest();
|
||||
var startTime = testTimeSeconds / 2; // start measuring half way through the test, to get past IO oddities
|
||||
renderIOScoringStarted(testTimeSeconds);
|
||||
renderIOCountdown(testTimeSeconds);
|
||||
var interval = setInterval(function () {
|
||||
testTimeSeconds -= 1;
|
||||
renderIOCountdown(testTimeSeconds);
|
||||
|
||||
if(testTimeSeconds == startTime) {
|
||||
logger.debug("Starting IO Perf Test starting at " + startTime + "s in")
|
||||
context.jamClient.FTUEStartIoPerfTest();
|
||||
}
|
||||
|
||||
if (testTimeSeconds == 0) {
|
||||
clearInterval(interval);
|
||||
renderIOScoringStopped();
|
||||
logger.debug("Ending IO Perf Test at " + testTimeSeconds + "s in")
|
||||
var io = context.jamClient.FTUEGetIoPerfData();
|
||||
lastIOScore = io;
|
||||
processIOScore(io);
|
||||
|
|
@ -1014,6 +1074,7 @@
|
|||
}
|
||||
|
||||
function beforeHide() {
|
||||
console.log("beforeHide:");
|
||||
$(window).off('focus', onFocus);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
(function(context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
|
||||
|
||||
// creates an iconic/graphical instrument selector. useful when there is minimal real-estate
|
||||
|
||||
$.fn.instrumentSelector = function(options) {
|
||||
|
||||
return this.each(function(index) {
|
||||
|
||||
function select(instrument_id) {
|
||||
if(instrument_id == null) {
|
||||
$currentInstrument.text('?');
|
||||
$currentInstrument.addClass('none');
|
||||
$select.data('instrument_id', null);
|
||||
}
|
||||
else {
|
||||
$currentInstrument.empty();
|
||||
$currentInstrument.removeClass('none');
|
||||
$currentInstrument.append('<img src="' + context.JK.getInstrumentIconMap24()[instrument_id].asset + '" />');
|
||||
$select.data('instrument_id', instrument_id);
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
$currentInstrument.btOff();
|
||||
}
|
||||
|
||||
function onInstrumentSelected() {
|
||||
var $li = $(this);
|
||||
var instrument_id = $li.attr('data-instrument-id');
|
||||
|
||||
select(instrument_id);
|
||||
close();
|
||||
$select.triggerHandler('instrument_selected', {instrument_id: instrument_id});
|
||||
return false;
|
||||
};
|
||||
|
||||
var $select = $(context._.template($('#template-icon-instrument-select').html(), {instruments:context.JK.getInstrumentIconMap24()}, { variable: 'data' }));
|
||||
var $ul = $select.find('ul');
|
||||
var $currentInstrument = $select.find('.current-instrument');
|
||||
|
||||
context.JK.hoverBubble($currentInstrument, $ul.html(), {
|
||||
trigger:'click',
|
||||
cssClass: 'icon-instrument-selector-popup',
|
||||
spikeGirth:0,
|
||||
spikeLength:0,
|
||||
width:150,
|
||||
closeWhenOthersOpen: true,
|
||||
preShow: function() {
|
||||
},
|
||||
postShow:function(container) {
|
||||
$(container).find('li').click(onInstrumentSelected)
|
||||
}
|
||||
});
|
||||
|
||||
$currentInstrument.text('?');
|
||||
|
||||
$(this).append($select);
|
||||
|
||||
this.instrumentSelectorClose = close;
|
||||
this.instrumentSelectorSet = select;
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.instrumentSelectorClose = function() {
|
||||
return this.each(function(index){
|
||||
if (jQuery.isFunction(this.instrumentSelectorClose)) {
|
||||
this.instrumentSelectorClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.instrumentSelectorSet = function(instrumentId) {
|
||||
return this.each(function(index){
|
||||
if (jQuery.isFunction(this.instrumentSelectorSet)) {
|
||||
this.instrumentSelectorSet(instrumentId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -91,49 +91,6 @@
|
|||
instrumentIconMap256[instrumentId] = {asset: "/assets/content/icon_instrument_" + icon + "256.png", name: instrumentId};
|
||||
});
|
||||
|
||||
context.JK.iconInstrumentSelect = function() {
|
||||
var $select = $(context._.template($('#template-icon-instrument-select').html(), {instruments:instrumentIconMap24}, { variable: 'data' }));
|
||||
var $ul = $select.find('ul');
|
||||
var $currentInstrument = $select.find('.current-instrument');
|
||||
|
||||
context.JK.hoverBubble($currentInstrument, $ul.html(), {
|
||||
trigger:'click',
|
||||
cssClass: 'icon-instrument-selector-popup',
|
||||
spikeGirth:0,
|
||||
spikeLength:0,
|
||||
width:150,
|
||||
closeWhenOthersOpen: true,
|
||||
preShow: function() {
|
||||
},
|
||||
postShow:function(container) {
|
||||
$(container).find('li').click(onInstrumentSelected)
|
||||
}});
|
||||
|
||||
function select(instrument_id) {
|
||||
$currentInstrument.empty();
|
||||
$currentInstrument.removeClass('none');
|
||||
$currentInstrument.append('<img src="' + instrumentIconMap24[instrument_id].asset + '" />');
|
||||
}
|
||||
function close() {
|
||||
$currentInstrument.btOff();
|
||||
}
|
||||
|
||||
function onInstrumentSelected() {
|
||||
var $li = $(this);
|
||||
var instrument_id = $li.attr('data-instrument-id');
|
||||
|
||||
select(instrument_id);
|
||||
close();
|
||||
$select.data('instrument_id', instrument_id);
|
||||
$select.triggerHandler('instrument_selected', {instrument_id: instrument_id});
|
||||
return false;
|
||||
};
|
||||
|
||||
$currentInstrument.text('?');
|
||||
|
||||
return $select;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a help bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
||||
* @param $element The element that should show the help when hovered
|
||||
|
|
@ -145,6 +102,7 @@
|
|||
if (!data) {
|
||||
data = {}
|
||||
}
|
||||
|
||||
var helpText = context._.template($('#template-help-' + templateName).html(), data, { variable: 'data' });
|
||||
|
||||
var holder = $('<div class="hover-bubble help-bubble"></div>');
|
||||
|
|
@ -165,7 +123,8 @@
|
|||
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
||||
*/
|
||||
context.JK.prodBubble = function($element, templateName, data, options) {
|
||||
options['trigger'] = 'now';
|
||||
options['trigger'] = 'none';
|
||||
options['clickAnywhereToClose'] = false
|
||||
var existingTimer = $element.data("prodTimer");
|
||||
if(existingTimer) {
|
||||
clearTimeout(existingTimer);
|
||||
|
|
@ -800,7 +759,7 @@
|
|||
}
|
||||
|
||||
context.JK.checkbox = function ($checkbox) {
|
||||
$checkbox.iCheck({
|
||||
return $checkbox.iCheck({
|
||||
checkboxClass: 'icheckbox_minimal',
|
||||
radioClass: 'iradio_minimal',
|
||||
inheritClass: true
|
||||
|
|
|
|||
|
|
@ -405,6 +405,8 @@
|
|||
|
||||
.num {
|
||||
position:absolute;
|
||||
height:29px;
|
||||
line-height:29px;
|
||||
}
|
||||
.track {
|
||||
margin-bottom: 15px;
|
||||
|
|
@ -506,8 +508,17 @@
|
|||
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-left:30px;
|
||||
margin-top:14px;
|
||||
font-weight:bold;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
p {
|
||||
padding-left:30px;
|
||||
margin-top:5px;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
input {
|
||||
|
|
@ -515,11 +526,32 @@
|
|||
margin:auto;
|
||||
width:30px;
|
||||
}
|
||||
|
||||
.iradio_minimal {
|
||||
margin-top:15px;
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.ftue-box {
|
||||
&.chat-inputs {
|
||||
height: 230px !important;
|
||||
overflow:auto;
|
||||
|
||||
p {
|
||||
white-space: nowrap;
|
||||
display:inline-block;
|
||||
height:32px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
white-space:nowrap;
|
||||
|
||||
.iradio_minimal {
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.watch-video {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@
|
|||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.track-instrument {
|
||||
position:absolute;
|
||||
top:85px;
|
||||
left:12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -404,11 +410,6 @@ table.vu td {
|
|||
border-radius:22px;
|
||||
}
|
||||
|
||||
.track-instrument {
|
||||
position:absolute;
|
||||
top:85px;
|
||||
left:12px;
|
||||
}
|
||||
|
||||
.track-gain {
|
||||
position:absolute;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
class ApiInvitedUsersController < ApiController
|
||||
class ApiInvitedUsersController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
class ApiLatencyTestersController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
def match
|
||||
# some day we can find the best latency tester to test against, now there is only one.
|
||||
@latency_tester = LatencyTester.first
|
||||
|
||||
respond_with_model(@latency_tester)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -3,6 +3,10 @@ class ClientsController < ApplicationController
|
|||
include ClientHelper
|
||||
include UsersHelper
|
||||
|
||||
|
||||
AUTHED = %W{friend}
|
||||
|
||||
|
||||
def index
|
||||
|
||||
# we want to enforce that /client is always the client view prefix
|
||||
|
|
@ -15,7 +19,10 @@ class ClientsController < ApplicationController
|
|||
render :layout => 'client'
|
||||
end
|
||||
|
||||
AUTHED = %W{friend}
|
||||
def latency_tester
|
||||
gon_properties
|
||||
render :layout => 'client'
|
||||
end
|
||||
|
||||
def auth_action
|
||||
if current_user
|
||||
|
|
@ -31,5 +38,4 @@ class ClientsController < ApplicationController
|
|||
redirect_to client_url
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @latency_tester
|
||||
|
||||
extends "api_latency_testers/show"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
object @latency_tester
|
||||
|
||||
attribute :id, :client_id
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
object @music_session
|
||||
object @music_session
|
||||
|
||||
if !current_user
|
||||
# there should be more data returned, but we need to think very carefully about what data is public for a music session
|
||||
|
|
|
|||
|
|
@ -12,4 +12,8 @@
|
|||
|
||||
<script type="text/template" id="template-help-ftue-watch-video">
|
||||
Be sure to watch the help video.
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-help-chat-not-enabled">
|
||||
You must first chose this option in order to activate a chat input.
|
||||
</script>
|
||||
|
|
@ -154,7 +154,7 @@
|
|||
.wizard-step{ 'layout-wizard-step' => "3", 'dialog-title' => "Configure Voice Chat", 'dialog-purpose' => "ConfigureVoiceChat" }
|
||||
.ftuesteps
|
||||
.clearall
|
||||
.help-text In this step, you will select, configure, and test your audio gear. Please watch the video for best instructions.
|
||||
.help-text In this step, you may set up a microphone to use for voice chat. Please watch the video for best instructions.
|
||||
.wizard-step-content
|
||||
.wizard-step-column
|
||||
%h2 Instructions
|
||||
|
|
@ -167,12 +167,14 @@
|
|||
%h2 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", checked:"unchecked"}
|
||||
%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
|
||||
.wizard-step-column
|
||||
%h2 Track Input Port(s)
|
||||
%h2 Voice Chat Input
|
||||
.ftue-box.chat-inputs
|
||||
|
||||
|
||||
|
|
@ -193,7 +195,7 @@
|
|||
.wizard-step-column
|
||||
.help-content
|
||||
When you have fully turned off the direct monitoring control (if any) on your audio interface,
|
||||
please click the Play busson below. If you hear the audio clearly, then your settings are correct,
|
||||
please click the Play button below. If you hear the audio clearly, then your settings are correct,
|
||||
and you can move ahead to the next step.
|
||||
If you use your audio interface for recording, and use the direct monitoring feature for recording,
|
||||
please note that you will need to remember to turn this feature off every time that you use the JamKazam service.
|
||||
|
|
@ -253,3 +255,9 @@
|
|||
.num {{data.num + 1}}:
|
||||
.track-target{'data-num' => '{{data.num}}', 'track-count' => 0}
|
||||
%span.placeholder None
|
||||
|
||||
%script{type: 'text/template', id: 'template-chat-input'}
|
||||
.chat-input
|
||||
%input{type:"radio", name: "chat-device", 'data-channel-id' => '{{data.id}}'}
|
||||
%p
|
||||
= '{{data.name}}'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
= render :partial => "jamServer"
|
||||
|
||||
:javascript
|
||||
$(function() {
|
||||
JK = JK || {};
|
||||
|
||||
JK.root_url = "#{root_url}"
|
||||
|
||||
<% if Rails.env == "development" %>
|
||||
// if in development mode, we assume you are running websocket-gateway
|
||||
// on the same host as you hit your server.
|
||||
JK.websocket_gateway_uri = "ws://" + location.hostname + ":6767/websocket";
|
||||
<% else %>
|
||||
// but in any other mode, just trust the config coming through gon
|
||||
JK.websocket_gateway_uri = gon.websocket_gateway_uri
|
||||
<% end %>
|
||||
if (console) { console.log("websocket_gateway_uri:" + JK.websocket_gateway_uri); }
|
||||
|
||||
|
||||
// If no trackVolumeObject (when not running in native client)
|
||||
// create a fake one.
|
||||
if (!(window.trackVolumeObject)) {
|
||||
window.trackVolumeObject = {
|
||||
bIsMediaFile: false,
|
||||
broadcast: false,
|
||||
clientID: "",
|
||||
instrumentID: "",
|
||||
master: false,
|
||||
monitor: false,
|
||||
mute: false,
|
||||
name: "",
|
||||
objectName: "",
|
||||
record: false,
|
||||
volL: 0,
|
||||
volR: 0,
|
||||
wigetID: ""
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Some things can't be initialized until we're connected. Put them here.
|
||||
function _initAfterConnect(connected) {
|
||||
if (this.didInitAfterConnect) return;
|
||||
this.didInitAfterConnect = true
|
||||
|
||||
if(!connected) {
|
||||
jamServer.initiateReconnect(null, true);
|
||||
}
|
||||
}
|
||||
|
||||
JK.app = JK.JamKazam();
|
||||
var jamServer = new JK.JamServer(JK.app);
|
||||
jamServer.initialize();
|
||||
|
||||
// If no jamClient (when not running in native client)
|
||||
// create a fake one.
|
||||
if (!(window.jamClient)) {
|
||||
var p2pMessageFactory = new JK.FakeJamClientMessages();
|
||||
window.jamClient = new JK.FakeJamClient(JK.app, p2pMessageFactory);
|
||||
window.jamClient.SetFakeRecordingImpl(new JK.FakeJamClientRecordings(JK.app, jamClient, p2pMessageFactory));
|
||||
}
|
||||
else if(false) { // set to true to time long running bridge calls
|
||||
var originalJamClient = window.jamClient;
|
||||
var interceptedJamClient = {};
|
||||
$.each(Object.keys(originalJamClient), function(i, key) {
|
||||
if(key.indexOf('(') > -1) {
|
||||
// this is a method. time it
|
||||
var jsKey = key.substring(0, key.indexOf('('))
|
||||
console.log("replacing " + jsKey)
|
||||
interceptedJamClient[jsKey] = function() {
|
||||
var original = originalJamClient[key]
|
||||
var start = new Date();
|
||||
if(key == "FTUEGetDevices()") {
|
||||
var returnVal = eval('originalJamClient.FTUEGetDevices(' + arguments[0] + ')');
|
||||
}
|
||||
else {
|
||||
var returnVal = original.apply(originalJamClient, arguments);
|
||||
}
|
||||
var time = new Date().getTime() - start.getTime();
|
||||
if(time >= 0) { // if 0, you'll see ALL bridge calls. If you set it to a higher value, you'll only see calls that are beyond that threshold
|
||||
console.error(time + "ms jamClient." + jsKey + ' returns=', returnVal);
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we need to intercept properties... but how?
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
window.jamClient = interceptedJamClient;
|
||||
}
|
||||
|
||||
// Let's get things rolling...
|
||||
//if (JK.currentUserId) {
|
||||
|
||||
// JK.app.initialize();
|
||||
|
||||
|
||||
JK.JamServer.connect() // singleton here defined in JamServer.js
|
||||
.done(function() {
|
||||
_initAfterConnect(true);
|
||||
})
|
||||
.fail(function() {
|
||||
_initAfterConnect(false);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
|
@ -34,6 +34,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/isp/ping:isp', :to => 'users#jnlp', :constraints => {:format => :jnlp}, :as => 'isp_ping'
|
||||
|
||||
match '/client', to: 'clients#index'
|
||||
match '/latency_tester', to: 'clients#latency_tester'
|
||||
|
||||
match '/confirm/:signup_token', to: 'users#signup_confirm', as: 'signup_confirm'
|
||||
|
||||
|
|
@ -411,6 +412,9 @@ SampleApp::Application.routes.draw do
|
|||
|
||||
# diagnostic
|
||||
match '/diagnostics' => 'api_diagnostics#create', :via => :post
|
||||
|
||||
# latency_tester
|
||||
match '/latency_testers' => 'api_latency_testers#match', :via => :get
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,7 +13,12 @@ class SpecDb
|
|||
db_config["database"] = "postgres"
|
||||
ActiveRecord::Base.establish_connection(db_config)
|
||||
ActiveRecord::Base.connection.execute("DROP DATABASE IF EXISTS #{db_test_name}")
|
||||
ActiveRecord::Base.connection.execute("CREATE DATABASE #{db_test_name}")
|
||||
if ENV['TABLESPACE']
|
||||
ActiveRecord::Base.connection.execute("CREATE DATABASE #{db_test_name} WITH tablespace=#{ENV["TABLESPACE"]}")
|
||||
else
|
||||
ActiveRecord::Base.connection.execute("CREATE DATABASE #{db_test_name}")
|
||||
end
|
||||
|
||||
db_config["database"] = db_test_name
|
||||
JamDb::Migrator.new.migrate(:dbname => db_config["database"], :user => db_config["username"], :password => db_config["password"], :host => db_config["host"])
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue