* VRFS-1047 mosttly done, aside from jamfet link

This commit is contained in:
Seth Call 2014-03-05 17:18:53 -06:00
parent 5eee96fb3e
commit 1c2585ba92
21 changed files with 224 additions and 152 deletions

View File

@ -12,5 +12,9 @@ module JamRuby
# music sessions
has_and_belongs_to_many :music_sessions, :class_name => "JamRuby::MusicSession", :join_table => "genres_music_sessions"
def to_s
description
end
end
end

View File

@ -76,13 +76,11 @@ module JamRuby
end
# creates a templated
def self.build_session_mount(music_session)
def self.build_session_mount(music_session, icecast_server)
# only public sessions get mounts currently
return nil unless music_session.fan_access
icecast_server = IcecastServer.find_best_server_for_user(music_session.creator)
mount = nil
if icecast_server && icecast_server.mount_template_id
# we have a server with an associated mount_template; we can create a mount automatically

View File

@ -24,7 +24,8 @@ module JamRuby
has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session
belongs_to :band, :inverse_of => :music_sessions, :class_name => "JamRuby::Band", :foreign_key => "band_id"
after_save :require_at_least_one_genre, :limit_max_genres, :sync_music_session_history
validate :require_at_least_one_genre, :limit_max_genres
after_save :sync_music_session_history
after_destroy do |obj|
JamRuby::MusicSessionHistory.removed_music_session(obj.id)
@ -269,7 +270,7 @@ module JamRuby
def require_at_least_one_genre
unless skip_genre_validation
if self.genres.count < Limits::MIN_GENRES_PER_SESSION
if self.genres.length < Limits::MIN_GENRES_PER_SESSION
errors.add(:genres, ValidationMessages::SESSION_GENRE_MINIMUM_NOT_MET)
end
end
@ -277,7 +278,7 @@ module JamRuby
def limit_max_genres
unless skip_genre_validation
if self.genres.count > Limits::MAX_GENRES_PER_SESSION
if self.genres.length > Limits::MAX_GENRES_PER_SESSION
errors.add(:genres, ValidationMessages::SESSION_GENRE_LIMIT_EXCEEDED)
end
end

View File

@ -144,7 +144,7 @@ module JamRuby
session_history.description = music_session.description unless music_session.description.nil?
session_history.user_id = music_session.creator.id
session_history.band_id = music_session.band.id unless music_session.band.nil?
session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR
session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR if music_session.genres.count > 0
session_history.fan_access = music_session.fan_access
session_history.save!
end

View File

@ -89,27 +89,33 @@ module JamRuby
if File.exist?(config_file) && !icecast_server.config_changed
@@log.info("config not changed. skipping run for server: #{icecast_server.server_id}")
else
# don't try to write to the file if for some reason the model isn't valid
# this could happen if an admin mucks around in the db directly
raise "icecast_server.id=#{icecast_server.server_id} not valid. errors=#{icecast_server.errors.inspect}" unless icecast_server.valid?
# write the new config to a temporary location
tmp_config = Dir::Tmpname.make_tmpname(["#{Dir.tmpdir}/icecast", '.xml'], nil)
buffer = nil
# allow no write to the server while dumping XML
icecast_server.with_lock do
# don't try to write to the file if for some reason the model isn't valid
# this could happen if an admin mucks around in the db directly
raise "icecast_server.id=#{icecast_server.server_id} not valid. errors=#{icecast_server.errors.inspect}" unless icecast_server.valid?
# write the new config to a temporary location
tmp_config = Dir::Tmpname.make_tmpname(["#{Dir.tmpdir}/icecast", '.xml'], nil)
File.open(tmp_config, 'w') do |f|
icecast_server.dumpXml(f)
end
# if written successfully, overwrite the current file
FileUtils.mv tmp_config, config_file
# reload server
reload
icecast_server.config_updated
buffer = StringIO.new
icecast_server.dumpXml(buffer)
end
buffer.rewind
File.open(tmp_config, 'w') do |f|
f.write buffer.read
end
# if written successfully, overwrite the current file
FileUtils.mv tmp_config, config_file
# reload server
reload
icecast_server.config_updated
end
@@log.info("successful update of config for server: #{icecast_server.server_id}")

View File

@ -176,29 +176,29 @@ describe IcecastMount do
end
it "no fan access means no mount" do
mount = IcecastMount.build_session_mount(hidden_music_session)
mount = IcecastMount.build_session_mount(hidden_music_session, IcecastServer.find_best_server_for_user(hidden_music_session.creator))
mount.should be_nil
end
it "with no servers" do
IcecastServer.count.should == 0
mount = IcecastMount.build_session_mount(public_music_session)
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.should be_nil
end
it "with a server that has a mount template" do
server1.mount_template.should_not be_nil
mount = IcecastMount.build_session_mount(public_music_session)
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.should_not be_nil
mount.save!
end
it "with a server that already has an associated mount" do
server1.mount_template.should_not be_nil
mount = IcecastMount.build_session_mount(public_music_session)
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.save!
mount = IcecastMount.build_session_mount(public_music_session2)
mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount.save!
server1.reload
server1.mounts.length.should == 2
@ -207,13 +207,13 @@ describe IcecastMount do
it "picks a second server once the 1st has been chosen" do
server1.touch
mount = IcecastMount.build_session_mount(public_music_session)
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.listeners = 1 # affect the weight
mount.save!
server2.touch
mount = IcecastMount.build_session_mount(public_music_session2)
mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount.save!
server1.reload
server1.mounts.length.should == 1
@ -224,17 +224,17 @@ describe IcecastMount do
it "picks the 1st server again once the 2nd has higher weight" do
server1.touch
mount = IcecastMount.build_session_mount(public_music_session)
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.listeners = 1 # affect the weight
mount.save!
server2.touch
mount = IcecastMount.build_session_mount(public_music_session2)
mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount.sourced = 1
mount.save!
mount = IcecastMount.build_session_mount(public_music_session3)
mount = IcecastMount.build_session_mount(public_music_session3, IcecastServer.find_best_server_for_user(public_music_session3.creator))
mount.listeners = 1
mount.save!

View File

@ -14,7 +14,7 @@ describe IcecastMountTemplate do
before(:each) do
server.touch
mount = IcecastMount.build_session_mount(music_session)
mount = IcecastMount.build_session_mount(music_session, IcecastServer.find_best_server_for_user(music_session.creator))
mount.save!
server.save!
server.config_updated

View File

@ -7,6 +7,15 @@ describe MusicSession do
IcecastServer.delete_all
IcecastMount.delete_all
end
describe "validations" do
it "genre must be set" do
music_session = FactoryGirl.build(:music_session)
music_session.genres = []
music_session.save.should be_false
music_session.errors[:genres].should == [ValidationMessages::SESSION_GENRE_MINIMUM_NOT_MET]
end
end
it 'can grant access to valid user' do
user1 = FactoryGirl.create(:user) # in the jam session
@ -461,5 +470,14 @@ describe MusicSession do
@music_session.get_connection_ids(exclude_client_id: @connection2.client_id, as_musician: true).should == [@connection1.client_id]
end
end
describe "autosave of music session history" do
it "is created on initial music session create" do
music_session = FactoryGirl.create(:music_session)
history = MusicSessionHistory.find(music_session.id)
history.genres.should == music_session.genres.first.id
end
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -6,6 +6,7 @@
context.JK.FeedItemRecording = function($parentElement, options){
var $feedItem = $parentElement;
var $name = $('.name', $feedItem);
var $description = $('.description', $feedItem);
var $musicians = $('.musician-detail', $feedItem);
var $controls = $('.recording-controls', $feedItem);
@ -67,11 +68,15 @@
$musicians.hide();
$description.css('height', $description.data('original-height'));
$description.dotdotdot();
$name.css('height', $name.data('original-height'));
$name.dotdotdot();
});
}
else {
$description.trigger('destroy.dot');
$description.data('original-height', $description.css('height')).css('height', 'auto');
$name.trigger('destroy.dot');
$name.data('original-height', $name.css('height')).css('height', 'auto');
$musicians.show();
$feedItem.animate({'max-height': '1000px'});
}

View File

@ -34,12 +34,11 @@
});
}
function updateSession(id, newSession, onSuccess) {
function updateSession(id, newSession) {
return $.ajax('/api/sessions/' + id, {
type: "PUT",
data : newSession,
dataType : 'json',
success: onSuccess
dataType : 'json'
});
}

View File

@ -1528,8 +1528,8 @@
return sessionModel.getCurrentSession();
};
this.refreshCurrentSession = function() {
sessionModel.refreshCurrentSession();
this.refreshCurrentSession = function(force) {
sessionModel.refreshCurrentSession(force);
};
this.setPromptLeave = function(_promptLeave) {

View File

@ -166,6 +166,12 @@
function refreshCurrentSession(force) {
// XXX use backend instead: https://jamkazam.atlassian.net/browse/VRFS-854
//logger.debug("SessionModel.refreshCurrentSession(" + currentSessionId +")");
if(force) {
logger.debug("refreshCurrentSession(force=true)")
}
else {
}
refreshCurrentSessionRest(sessionChanged, force);
}

View File

@ -96,12 +96,12 @@
if (typeof newSessionInfo.genres === "string") {
newSessionInfo.genres = [newSessionInfo.genres];
}
rest.updateSession(id, newSessionInfo, settingsSaved);
rest.updateSession(id, newSessionInfo).done(settingsSaved);
}
function settingsSaved(response) {
// No response returned from this call. 204.
sessionScreen.refreshCurrentSession();
sessionScreen.refreshCurrentSession(true);
app.layout.closeDialog('session-settings');
}

View File

@ -1,69 +1,87 @@
(function(context,$) {
(function (context, $) {
"use strict";
"use strict";
context.JK = context.JK || {};
context.JK = context.JK || {};
var welcomeRoot;
var welcomeRoot;
var rest = context.JK.Rest();
function initialize() {
function initialize() {
welcomeRoot = $('.landing-content .wrapper .welcome')
welcomeRoot = $('.landing-content .wrapper .welcome')
$('#signup').click(function(e) {
context.JK.app.layout.showDialog('signup-dialog');
$('#signup').click(function (e) {
context.JK.app.layout.showDialog('signup-dialog');
e.preventDefault();
return false;
});
$('#signin').click(function (e) {
if (context.JK.currentUserId) {
rest.getUserDetail()
.done(function () {
e.preventDefault();
window.location = '/client';
return false;
});
$('#signin').click(function(e) {
})
.fail(function () {
context.JK.app.layout.showDialog('signin-dialog');
e.preventDefault();
return false;
});
$('.carousel').carousel({
hAlign:'center',
vAlign:'bottom',
vMargin:.5,
reflection:true,
reflectionColor:'0,0,0',
directionNav:false,
frontWidth:424,
frontHeight:263,
carouselWidth:750,
carouselHeight:440,
slidesPerScroll:3,
backOpacity:2
});
$.each($('.feed-entry'), function(index, feedEntry) {
var $feedEntry = $(this);
if($feedEntry.is('.recording-entry')) {
new context.JK.FeedItemRecording($feedEntry);
}
else {
new context.JK.FeedItemSession($feedEntry);
}
})
context.JK.TickDuration('.feed-entry.music-session-history-entry .inprogress .tick-duration');
if($.QueryString['showVideo']) {
// pop a video automatically
var slides = $('.slideItem');
$.each(slides, function(i, slide) {
slide = $(slide)
if(slide.attr('data-video-url') == $.QueryString['showVideo']) {
slide.click();
}
});
})
}
else {
// don't bother checking if no context.JK.currentUserId
context.JK.app.layout.showDialog('signin-dialog');
e.preventDefault();
return false;
}
});
$('.carousel').carousel({
hAlign: 'center',
vAlign: 'bottom',
vMargin: .5,
reflection: true,
reflectionColor: '0,0,0',
directionNav: false,
frontWidth: 424,
frontHeight: 263,
carouselWidth: 750,
carouselHeight: 440,
slidesPerScroll: 3,
backOpacity: 2
});
$('.carousel').show()
$.each($('.feed-entry'), function (index, feedEntry) {
var $feedEntry = $(this);
if ($feedEntry.is('.recording-entry')) {
new context.JK.FeedItemRecording($feedEntry);
}
else {
new context.JK.FeedItemSession($feedEntry);
}
})
context.JK.TickDuration('.feed-entry.music-session-history-entry .inprogress .tick-duration');
if ($.QueryString['showVideo']) {
// pop a video automatically
var slides = $('.slideItem');
$.each(slides, function (i, slide) {
slide = $(slide)
if (slide.attr('data-video-url') == $.QueryString['showVideo']) {
slide.click();
}
});
}
}
context.JK.WelcomePage = initialize;
context.JK.WelcomePage = initialize;
})(window, jQuery);

View File

@ -209,9 +209,13 @@
.name {
font-weight:bold;
min-height:16px;
font-size:14px;
line-height:14px;
height:16px;
overflow:hidden;
whitespace:nowrap;
text-overflow:ellipsis;
white-space:normal;
}
.description {

View File

@ -79,6 +79,7 @@ Version: 1.1
.carousel
{
display:none;
position :relative ;
margin :30px auto 0;
width :auto;

View File

@ -5,9 +5,9 @@ require 'builder'
class Slide
attr_accessor :img_url, :header, :vid_url
def initialize(type, img_url, vid_url)
def initialize(header, img_url, vid_url)
@img_url = img_url # preview image
@header = "jamkazam for #{type}" #
@header = header
@vid_url = vid_url + '?autoplay=1'
end
end
@ -198,12 +198,12 @@ class UsersController < ApplicationController
def welcome
@slides = [
Slide.new("musicians", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("fans", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("bands", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("musicians", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("fans", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("bands", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s")
Slide.new("JamKazam Overview", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("Getting Started", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("Playing in a Session", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("JamKazam Overview", "web/carousel_musicians.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("Getting Started", "web/carousel_fans.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s"),
Slide.new("Playing in a Session", "web/carousel_bands.jpg", "http://www.youtube.com/embed/eaYNM7p6Z5s")
]
@promo_buzz = PromoBuzz.active

View File

@ -12,64 +12,76 @@ MusicSessionManager < BaseManager
def create(user, client_id, description, musician_access, approval_required, fan_chat, fan_access, band, genres, tracks, legal_terms)
return_value = nil
ActiveRecord::Base.transaction do
# check if we are connected to rabbitmq
music_session = MusicSession.new
music_session.id = SecureRandom.uuid
music_session.creator = user
music_session.description = description
music_session.musician_access = musician_access
music_session.approval_required = approval_required
music_session.fan_chat = fan_chat
music_session.fan_access = fan_access
music_session.band = band
music_session.legal_terms = legal_terms
time = Benchmark.realtime do
ActiveRecord::Base.transaction do
unless genres.nil?
genres.each do |genre_id|
loaded_genre = Genre.find(genre_id)
music_session.genres << loaded_genre
end
end
# we need to lock the icecast server in this transaction for writing, to make sure thath IcecastConfigWriter
# doesn't dumpXML as we are changing the server's configuraion
icecast_server = IcecastServer.find_best_server_for_user(user) if fan_access
icecast_server.lock! if icecast_server
if fan_access
# create an icecast mount since regular users can listen in to the broadcast
music_session.mount = IcecastMount.build_session_mount(music_session)
end
# check if we are connected to rabbitmq
music_session = MusicSession.new
music_session.id = SecureRandom.uuid
music_session.creator = user
music_session.description = description
music_session.musician_access = musician_access
music_session.approval_required = approval_required
music_session.fan_chat = fan_chat
music_session.fan_access = fan_access
music_session.band = band
music_session.legal_terms = legal_terms
music_session.save
unless music_session.errors.any?
# save session parameters for next session
User.save_session_settings(user, music_session)
# auto-join this user into the newly created session
as_musician = true
connection = ConnectionManager.new.join_music_session(user, client_id, music_session, as_musician, tracks)
unless connection.errors.any?
user.update_progression_field(:first_music_session_at)
MusicSessionUserHistory.save(music_session.id, user.id, client_id, tracks)
unless band.nil?
Notification.send_band_session_join(music_session, band)
unless genres.nil?
genres.each do |genre_id|
loaded_genre = Genre.find(genre_id)
music_session.genres << loaded_genre
end
end
if fan_access
# create an icecast mount since regular users can listen in to the broadcast
music_session.mount = IcecastMount.build_session_mount(music_session, icecast_server)
end
music_session.save
unless music_session.errors.any?
# save session parameters for next session
User.save_session_settings(user, music_session)
# auto-join this user into the newly created session
as_musician = true
connection = ConnectionManager.new.join_music_session(user, client_id, music_session, as_musician, tracks)
unless connection.errors.any?
user.update_progression_field(:first_music_session_at)
MusicSessionUserHistory.save(music_session.id, user.id, client_id, tracks)
unless band.nil?
Notification.send_band_session_join(music_session, band)
end
return_value = music_session
else
return_value = connection
# rollback the transaction to make sure nothing is disturbed in the database
raise ActiveRecord::Rollback
end
return_value = music_session
else
return_value = connection
return_value = music_session
# rollback the transaction to make sure nothing is disturbed in the database
raise ActiveRecord::Rollback
end
else
return_value = music_session
# rollback the transaction to make sure nothing is disturbed in the database
raise ActiveRecord::Rollback
end
end
return return_value
if time > 2
@log.warn "creating a music session took #{time*1000} milliseconds"
end
return_value
end
# Update the session. If a field is left out (meaning, it's set to nil), it's not updated.