731 lines
24 KiB
Ruby
731 lines
24 KiB
Ruby
module JamRuby
|
|
class ActiveMusicSession < ActiveRecord::Base
|
|
|
|
@@log = Logging.logger[ActiveMusicSession]
|
|
|
|
self.primary_key = 'id'
|
|
|
|
self.table_name = 'active_music_sessions'
|
|
|
|
attr_accessor :legal_terms, :max_score
|
|
|
|
belongs_to :claimed_recording, :class_name => "JamRuby::ClaimedRecording", :foreign_key => "claimed_recording_id", :inverse_of => :playing_sessions
|
|
belongs_to :claimed_recording_initiator, :class_name => "JamRuby::User", :inverse_of => :playing_claimed_recordings, :foreign_key => "claimed_recording_initiator_id"
|
|
|
|
has_one :music_session, :class_name => "JamRuby::MusicSession", :foreign_key => 'music_session_id'
|
|
has_one :mount, :class_name => "JamRuby::IcecastMount", :inverse_of => :music_session, :foreign_key => 'music_session_id'
|
|
belongs_to :creator, :class_name => 'JamRuby::User', :foreign_key => :user_id
|
|
|
|
has_many :connections, :class_name => "JamRuby::Connection", foreign_key: :music_session_id
|
|
has_many :users, :through => :connections, :class_name => "JamRuby::User"
|
|
has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session, foreign_key: :music_session_id
|
|
has_many :chats, :class_name => "JamRuby::ChatMessages", :foreign_key => "session_id"
|
|
validates :creator, :presence => true
|
|
validate :creator_is_musician
|
|
validate :no_new_playback_while_playing
|
|
|
|
after_create :started_session
|
|
|
|
after_destroy do |obj|
|
|
JamRuby::MusicSession.removed_music_session(obj.id)
|
|
end
|
|
|
|
#default_scope :select => "*, 0 as score"
|
|
|
|
def attributes
|
|
super.merge('max_score' => self.max_score)
|
|
end
|
|
|
|
def max_score
|
|
nil unless has_attribute?(:max_score)
|
|
read_attribute(:max_score).to_i
|
|
end
|
|
|
|
before_create :create_uuid
|
|
def create_uuid
|
|
#self.id = SecureRandom.uuid
|
|
end
|
|
|
|
def before_destroy
|
|
self.mount.destroy if self.mount
|
|
end
|
|
|
|
def creator_is_musician
|
|
unless creator.musician?
|
|
errors.add(:creator, ValidationMessages::MUST_BE_A_MUSICIAN)
|
|
end
|
|
end
|
|
|
|
def no_new_playback_while_playing
|
|
# if we previous had a claimed recording and are trying to set one
|
|
# and if also the previous initiator is different than the current one... it's a no go
|
|
if !claimed_recording_id_was.nil? && !claimed_recording_id.nil? &&
|
|
claimed_recording_initiator_id_was != claimed_recording_initiator_id
|
|
errors.add(:claimed_recording, ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS)
|
|
end
|
|
end
|
|
|
|
# returns an array of client_id's that are in this session
|
|
# if as_musician is nil, all connections in the session ,regardless if it's a musician or not or not
|
|
# you can also exclude a client_id from the returned set by setting exclude_client_id
|
|
def get_connection_ids(options = {})
|
|
as_musician = options[:as_musician]
|
|
exclude_client_id = options[:exclude_client_id]
|
|
|
|
where = { :music_session_id => self.id }
|
|
where[:as_musician] = as_musician unless as_musician.nil?
|
|
|
|
exclude = "client_id != '#{exclude_client_id}'"unless exclude_client_id.nil?
|
|
|
|
Connection.select(:client_id).where(where).where(exclude).map(&:client_id)
|
|
end
|
|
|
|
# This is a little confusing. You can specify *BOTH* friends_only and my_bands_only to be true
|
|
# If so, then it's an OR condition. If both are false, you can get sessions with anyone.
|
|
def self.index(current_user, options = {})
|
|
participants = options[:participants]
|
|
genres = options[:genres]
|
|
keyword = options[:keyword]
|
|
friends_only = options[:friends_only].nil? ? false : options[:friends_only]
|
|
my_bands_only = options[:my_bands_only].nil? ? false : options[:my_bands_only]
|
|
as_musician = options[:as_musician].nil? ? true : options[:as_musician]
|
|
|
|
query = ActiveMusicSession
|
|
.joins(
|
|
%Q{
|
|
INNER JOIN
|
|
music_sessions
|
|
ON
|
|
active_music_sessions.id = music_sessions.id
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
INNER JOIN
|
|
connections
|
|
ON
|
|
active_music_sessions.id = connections.music_session_id
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
friendships
|
|
ON
|
|
connections.user_id = friendships.user_id
|
|
AND
|
|
friendships.friend_id = '#{current_user.id}'
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
invitations
|
|
ON
|
|
invitations.music_session_id = active_music_sessions.id
|
|
AND
|
|
invitations.receiver_id = '#{current_user.id}'
|
|
}
|
|
)
|
|
.group(
|
|
%Q{
|
|
active_music_sessions.id
|
|
}
|
|
)
|
|
.order(
|
|
%Q{
|
|
SUM(CASE WHEN invitations.id IS NULL THEN 0 ELSE 1 END) DESC,
|
|
SUM(CASE WHEN friendships.user_id IS NULL THEN 0 ELSE 1 END) DESC,
|
|
active_music_sessions.created_at DESC
|
|
}
|
|
)
|
|
|
|
if as_musician
|
|
query = query.where(
|
|
%Q{
|
|
musician_access = true
|
|
OR
|
|
invitations.id IS NOT NULL
|
|
}
|
|
)
|
|
else
|
|
# if you are trying to join the session as a fan/listener,
|
|
# we have to have a mount, fan_access has to be true, and we have to allow for the reload of icecast to have taken effect
|
|
query = query.joins('INNER JOIN icecast_mounts ON icecast_mounts.music_session_id = active_music_sessions.id INNER JOIN icecast_servers ON icecast_mounts.icecast_server_id = icecast_servers.id')
|
|
query = query.where('music_sessions.fan_access = true')
|
|
query = query.where("(active_music_sessions.created_at < icecast_servers.config_updated_at)")
|
|
end
|
|
|
|
query = query.where("music_sessions.description like '%#{keyword}%'") unless keyword.nil?
|
|
query = query.where("connections.user_id" => participants.split(',')) unless participants.nil?
|
|
query = query.where("music_sessions.genre_id in (?)", genres) unless genres.nil?
|
|
|
|
if my_bands_only
|
|
query = query.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
bands_musicians
|
|
ON
|
|
bands_musicians.user_id = '#{current_user.id}'
|
|
}
|
|
)
|
|
end
|
|
|
|
if my_bands_only || friends_only
|
|
query = query.where(
|
|
%Q{
|
|
#{friends_only ? "friendships.user_id IS NOT NULL" : "false"}
|
|
OR
|
|
#{my_bands_only ? "bands_musicians.band_id = music_sessions.band_id" : "false"}
|
|
}
|
|
)
|
|
end
|
|
|
|
return query
|
|
end
|
|
|
|
# This is a little confusing. You can specify *BOTH* friends_only and my_bands_only to be true
|
|
# If so, then it's an OR condition. If both are false, you can get sessions with anyone.
|
|
# note, this is mostly the same as above but includes paging through the result and and scores.
|
|
# thus it needs the client_id...
|
|
def self.nindex(current_user, options = {})
|
|
client_id = options[:client_id]
|
|
participants = options[:participants]
|
|
genres = options[:genres]
|
|
keyword = options[:keyword]
|
|
friends_only = options[:friends_only].nil? ? false : options[:friends_only]
|
|
my_bands_only = options[:my_bands_only].nil? ? false : options[:my_bands_only]
|
|
as_musician = options[:as_musician].nil? ? true : options[:as_musician]
|
|
offset = options[:offset]
|
|
limit = options[:limit]
|
|
|
|
connection = Connection.where(client_id: client_id).first!
|
|
locidispid = connection.locidispid
|
|
|
|
query = ActiveMusicSession
|
|
.select("active_music_sessions.*, max(coalesce(current_scores.score, 1000)) as max_score") # 1000 is higher than the allowed max of 999
|
|
.joins(
|
|
%Q{
|
|
INNER JOIN
|
|
music_sessions
|
|
ON
|
|
active_music_sessions.id = music_sessions.id
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
INNER JOIN
|
|
connections
|
|
ON
|
|
active_music_sessions.id = connections.music_session_id
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
current_scores
|
|
ON
|
|
current_scores.alocidispid = connections.locidispid
|
|
AND
|
|
current_scores.blocidispid = #{locidispid}
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
friendships
|
|
ON
|
|
connections.user_id = friendships.user_id
|
|
AND
|
|
friendships.friend_id = '#{current_user.id}'
|
|
}
|
|
)
|
|
.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
invitations
|
|
ON
|
|
invitations.music_session_id = active_music_sessions.id
|
|
AND
|
|
invitations.receiver_id = '#{current_user.id}'
|
|
}
|
|
)
|
|
.group(
|
|
%Q{
|
|
active_music_sessions.id
|
|
}
|
|
)
|
|
.order(
|
|
%Q{
|
|
SUM(CASE WHEN invitations.id IS NULL THEN 0 ELSE 1 END) DESC,
|
|
SUM(CASE WHEN friendships.user_id IS NULL THEN 0 ELSE 1 END) DESC,
|
|
active_music_sessions.created_at DESC
|
|
}
|
|
)
|
|
|
|
if (offset)
|
|
query = query.offset(offset)
|
|
end
|
|
|
|
if (limit)
|
|
query = query.limit(limit)
|
|
end
|
|
|
|
if as_musician
|
|
query = query.where(
|
|
%Q{
|
|
musician_access = true
|
|
OR
|
|
music_sessions.user_id = '#{current_user.id}'
|
|
OR
|
|
invitations.id IS NOT NULL
|
|
}
|
|
)
|
|
else
|
|
# if you are trying to join the session as a fan/listener,
|
|
# we have to have a mount, fan_access has to be true, and we have to allow for the reload of icecast to have taken effect
|
|
query = query.joins('INNER JOIN icecast_mounts ON icecast_mounts.music_session_id = active_music_sessions.id INNER JOIN icecast_servers ON icecast_mounts.icecast_server_id = icecast_servers.id')
|
|
query = query.where('music_sessions.fan_access = true')
|
|
query = query.where("(active_music_sessions.created_at < icecast_servers.config_updated_at)")
|
|
end
|
|
|
|
query = query.where("music_sessions.description like '%#{keyword}%'") unless keyword.nil?
|
|
query = query.where("connections.user_id" => participants.split(',')) unless participants.nil?
|
|
query = query.where("music_sessions.genre_id in (?)", genres) unless genres.nil?
|
|
|
|
if my_bands_only
|
|
query = query.joins(
|
|
%Q{
|
|
LEFT OUTER JOIN
|
|
bands_musicians
|
|
ON
|
|
bands_musicians.user_id = '#{current_user.id}'
|
|
}
|
|
)
|
|
end
|
|
|
|
if my_bands_only || friends_only
|
|
query = query.where(
|
|
%Q{
|
|
#{friends_only ? "friendships.user_id IS NOT NULL" : "false"}
|
|
OR
|
|
#{my_bands_only ? "bands_musicians.band_id = music_sessions.band_id" : "false"}
|
|
}
|
|
)
|
|
end
|
|
|
|
return query
|
|
end
|
|
|
|
# initialize the two temporary tables we use to drive ams_index and ams_users
|
|
def self.ams_init(current_user, options = {})
|
|
client_id = options[:client_id]
|
|
|
|
connection = Connection.where(user_id: current_user.id, client_id: client_id).first!
|
|
my_locidispid = connection.locidispid
|
|
# 13 is an average audio gear value we use if they have not qualified any gear
|
|
my_audio_latency = connection.last_jam_audio_latency || current_user.last_jam_audio_latency || 13
|
|
locidispid_expr = my_locidispid ? "#{my_locidispid}::bigint" : '0::bigint'
|
|
|
|
self.connection.execute("select ams_index('#{current_user.id}'::varchar, #{locidispid_expr}, #{my_audio_latency}::integer)").check
|
|
end
|
|
|
|
# Generate a list of music sessions (that are active) filtered by genre, language, keyword, and sorted
|
|
# (and tagged) by rsvp'd (1st), invited (2nd), and musician can join (3rd). within a group tagged the
|
|
# same, sorted by score. date seems irrelevant as these are active sessions. ams_init must be called
|
|
# first.
|
|
def self.ams_query(current_user, options = {})
|
|
session_id = options[:session_id]
|
|
client_id = options[:client_id]
|
|
genre = options[:genre]
|
|
lang = options[:lang]
|
|
keyword = options[:keyword]
|
|
offset = options[:offset]
|
|
limit = options[:limit]
|
|
day = options[:day]
|
|
timezone_offset = options[:timezone_offset]
|
|
|
|
query = MusicSession
|
|
.select('music_sessions.*')
|
|
|
|
# this is not really needed when ams_music_session_tmp is joined
|
|
# unless there is something specific we need out of active_music_sessions
|
|
# query = query.joins(
|
|
# %Q{
|
|
# INNER JOIN
|
|
# active_music_sessions
|
|
# ON
|
|
# active_music_sessions.id = music_sessions.id
|
|
# }
|
|
# )
|
|
# .select('1::integer as tag, 15::integer as latency')
|
|
|
|
# integrate ams_music_session_tmp into the processing
|
|
# then we can join ams_music_session_tmp and not join active_music_sessions
|
|
query = query.joins(
|
|
%Q{
|
|
INNER JOIN
|
|
ams_music_session_tmp
|
|
ON
|
|
ams_music_session_tmp.music_session_id = music_sessions.id
|
|
}
|
|
)
|
|
.select('ams_music_session_tmp.tag, ams_music_session_tmp.latency')
|
|
|
|
query = query.order(
|
|
%Q{
|
|
tag, latency, music_sessions.id
|
|
}
|
|
)
|
|
.group(
|
|
%Q{
|
|
tag, latency, music_sessions.id
|
|
}
|
|
)
|
|
|
|
# if not specified, default offset to 0
|
|
offset ||= 0
|
|
offset = offset.to_i
|
|
# if not specified, default limit to 20
|
|
limit ||= 20
|
|
limit = limit.to_i
|
|
|
|
query = query.offset(offset)
|
|
query = query.limit(limit)
|
|
query = query.where("music_sessions.genre_id = ?", genre) unless genre.blank?
|
|
query = query.where('music_sessions.language = ?', lang) unless lang.blank?
|
|
query = query.where('music_sessions.id = ?', session_id) unless session_id.blank?
|
|
query = query.where("(description_tsv @@ to_tsquery('jamenglish', ?))", ActiveRecord::Base.connection.quote(keyword) + ':*') unless keyword.blank?
|
|
|
|
if !day.blank? && !timezone_offset.blank?
|
|
begin
|
|
day = Date.parse(day)
|
|
next_day = day + 1
|
|
timezone_offset = timezone_offset.to_i
|
|
if timezone_offset > 0
|
|
timezone_offset = "+#{timezone_offset}"
|
|
end
|
|
query = query.where("scheduled_start BETWEEN TIMESTAMP WITH TIME ZONE '#{day} 00:00:00#{timezone_offset}'
|
|
AND TIMESTAMP WITH TIME ZONE '#{next_day} 00:00:00#{timezone_offset}'")
|
|
rescue Exception => e
|
|
# do nothing. bad date probably
|
|
@@log.warn("unable to parse day=#{day}, timezone_offset=#{timezone_offset}, e=#{e}")
|
|
end
|
|
end
|
|
|
|
return query
|
|
end
|
|
|
|
# returns the set of users in a music_sessions and the music_session they are in and their latency.
|
|
# ams_init must be called first.
|
|
# user.audio_latency / 2 , + other_user.audio_latency of them / 2, + network latency /2
|
|
def self.ams_users
|
|
return User.select('users.*, ams_users_tmp.music_session_id, ams_users_tmp.latency')
|
|
.joins(
|
|
%Q{
|
|
INNER JOIN
|
|
ams_users_tmp
|
|
ON
|
|
ams_users_tmp.user_id = users.id
|
|
}
|
|
)
|
|
.order('ams_users_tmp.music_session_id, ams_users_tmp.user_id')
|
|
end
|
|
|
|
# wrap me in a transaction!
|
|
# note that these queries must be actualized before the end of the transaction
|
|
# else the temporary tables created by sms_init will be gone.
|
|
def self.ams_index(current_user, params)
|
|
ActiveMusicSession.ams_init(current_user, params)
|
|
|
|
music_sessions = ActiveMusicSession.ams_query(current_user, params).all
|
|
|
|
music_session_users = ActiveMusicSession.ams_users.all
|
|
|
|
user_scores = {}
|
|
music_session_users.each do |user|
|
|
user_scores[user.id] = {latency: user.latency}
|
|
end
|
|
|
|
[music_sessions, user_scores]
|
|
end
|
|
|
|
def self.participant_create user, music_session_id, client_id, as_musician, tracks, audio_latency
|
|
music_session = MusicSession.find(music_session_id)
|
|
|
|
if music_session.active_music_session
|
|
connection = nil
|
|
active_music_session = nil
|
|
ActiveRecord::Base.transaction do
|
|
|
|
active_music_session = ActiveMusicSession.find(music_session_id)
|
|
|
|
active_music_session.with_lock do # VRFS-1297
|
|
active_music_session.tick_track_changes
|
|
connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency)
|
|
|
|
if connection.errors.any?
|
|
# rollback the transaction to make sure nothing is disturbed in the database
|
|
raise ActiveRecord::Rollback
|
|
end
|
|
end
|
|
end
|
|
|
|
unless connection.errors.any?
|
|
user.update_progression_field(:first_music_session_at)
|
|
MusicSessionUserHistory.save(music_session_id, user.id, client_id, tracks)
|
|
|
|
if as_musician
|
|
# send to session participants
|
|
Notification.send_session_join(active_music_session, connection, user)
|
|
|
|
# send "musician joined session" notification only if it's not a band session since there will be a "band joined session" notification
|
|
if music_session.band.nil?
|
|
Notification.send_musician_session_join(active_music_session, user)
|
|
end
|
|
end
|
|
end
|
|
|
|
connection
|
|
else
|
|
return_value = nil
|
|
|
|
time = Benchmark.realtime do
|
|
ActiveRecord::Base.transaction do
|
|
|
|
# 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 music_session.fan_access
|
|
icecast_server.lock! if icecast_server
|
|
|
|
# check if we are connected to rabbitmq
|
|
active_music_session = ActiveMusicSession.new
|
|
active_music_session.id = music_session.id # copy the .id from music_session to active_music_session
|
|
active_music_session.creator = user
|
|
|
|
if music_session.fan_access
|
|
# create an icecast mount since regular users can listen in to the broadcast
|
|
active_music_session.mount = IcecastMount.build_session_mount(music_session, active_music_session, icecast_server)
|
|
end
|
|
|
|
active_music_session.save
|
|
|
|
unless active_music_session.errors.any?
|
|
music_session.started_at = active_music_session.created_at
|
|
music_session.save(:validate => false)
|
|
|
|
# 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, active_music_session, as_musician, tracks, audio_latency)
|
|
|
|
unless connection.errors.any?
|
|
user.update_progression_field(:first_music_session_at)
|
|
MusicSessionUserHistory.save(active_music_session.id, user.id, client_id, tracks)
|
|
|
|
# only send this notification if it's a band session
|
|
unless music_session.band.nil?
|
|
Notification.send_band_session_join(active_music_session, music_session.band)
|
|
end
|
|
|
|
return_value = connection
|
|
else
|
|
return_value = connection
|
|
# rollback the transaction to make sure nothing is disturbed in the database
|
|
raise ActiveRecord::Rollback
|
|
end
|
|
else
|
|
return_value = active_music_session
|
|
# rollback the transaction to make sure nothing is disturbed in the database
|
|
raise ActiveRecord::Rollback
|
|
end
|
|
end
|
|
end
|
|
|
|
if time > 2
|
|
Logging.logger[self].warn "creating a music session took #{time*1000} milliseconds"
|
|
end
|
|
|
|
return_value
|
|
end
|
|
end
|
|
|
|
# Verifies that the specified user can join this music session
|
|
def can_join? user, as_musician
|
|
if as_musician
|
|
if !user.musician
|
|
return false # "a fan can not join a music session as a musician"
|
|
raise PermissionError, "a fan can not join a music session as a musician"
|
|
end
|
|
|
|
if self.musician_access
|
|
if self.approval_required
|
|
return self.invited_musicians.exists?(user)
|
|
else
|
|
return true
|
|
end
|
|
|
|
else
|
|
# the creator can always join, and the invited users can join
|
|
return self.creator == user || self.invited_musicians.exists?(user)
|
|
end
|
|
else
|
|
# it's a fan, and the only way a fan can join is if fan_access is true
|
|
return self.fan_access
|
|
end
|
|
|
|
end
|
|
|
|
# Verifies that the specified user can see this music session
|
|
def can_see? user
|
|
if self.musician_access || self.fan_access
|
|
true
|
|
else
|
|
self.creator == user || self.invited_musicians.exists?(user)
|
|
end
|
|
end
|
|
|
|
# Verifies that the specified user can delete this music session
|
|
def can_delete? user
|
|
# the creator can delete
|
|
self.creator == user
|
|
end
|
|
|
|
def access? user
|
|
music_session.part_of_session? user
|
|
end
|
|
|
|
def most_recent_recording
|
|
recordings.where(:music_session_id => self.id).order('created_at desc').limit(1).first
|
|
end
|
|
|
|
# is this music session currently recording?
|
|
def is_recording?
|
|
recordings.where(:duration => nil).count > 0
|
|
end
|
|
|
|
def is_playing_recording?
|
|
!self.claimed_recording.nil?
|
|
end
|
|
|
|
def recording
|
|
recordings.where(:duration => nil).first
|
|
end
|
|
|
|
# stops any active recording
|
|
def stop_recording
|
|
current_recording = self.recording
|
|
current_recording.stop unless current_recording.nil?
|
|
end
|
|
|
|
def claimed_recording_start(owner, claimed_recording)
|
|
self.claimed_recording = claimed_recording
|
|
self.claimed_recording_initiator = owner
|
|
self.save
|
|
end
|
|
|
|
def claimed_recording_stop
|
|
self.claimed_recording = nil
|
|
self.claimed_recording_initiator = nil
|
|
self.save
|
|
end
|
|
|
|
def invitations
|
|
music_session.invitations
|
|
end
|
|
|
|
def invited_musicians
|
|
music_session.invited_musicians
|
|
end
|
|
|
|
def join_requests
|
|
music_session.join_requests
|
|
end
|
|
|
|
def fan_invitations
|
|
music_session.fan_invitations
|
|
end
|
|
|
|
def to_s
|
|
description
|
|
end
|
|
|
|
def musician_access
|
|
music_session.musician_access
|
|
end
|
|
|
|
def fan_access
|
|
music_session.fan_access
|
|
end
|
|
|
|
def description
|
|
music_session.description
|
|
end
|
|
|
|
def name
|
|
music_session.name
|
|
end
|
|
|
|
def genre
|
|
music_session.genre
|
|
end
|
|
|
|
def fan_chat
|
|
music_session.fan_chat
|
|
end
|
|
|
|
def band
|
|
music_session.band
|
|
end
|
|
|
|
def approval_required
|
|
music_session.approval_required
|
|
end
|
|
|
|
def music_notations
|
|
music_session.music_notations
|
|
end
|
|
|
|
def tick_track_changes
|
|
self.track_changes_counter += 1
|
|
self.save!(:validate => false)
|
|
end
|
|
|
|
def connected_participant_count
|
|
Connection.where(:music_session_id => self.id,
|
|
:aasm_state => Connection::CONNECT_STATE.to_s,
|
|
:as_musician => true)
|
|
.count
|
|
end
|
|
|
|
def started_session
|
|
raise "active_music_sessions.id must be set by caller" unless self.id
|
|
# associate this active_music_session with the music_session formally
|
|
session = MusicSession.find(self.id)
|
|
session.active_music_session = self
|
|
self.music_session = session # needed because of the Google Analytics below in some test cases
|
|
session.scheduled_start = self.created_at unless session.scheduled_start
|
|
session.save!
|
|
|
|
GoogleAnalyticsEvent.track_session_duration(self)
|
|
GoogleAnalyticsEvent.track_band_real_session(self)
|
|
end
|
|
|
|
|
|
def self.sync(session_history)
|
|
music_session = MusicSession.find_by_id(session_history.id)
|
|
|
|
if music_session.nil?
|
|
music_session = MusicSession.new
|
|
music_session.id = session_history.id
|
|
end
|
|
|
|
music_session.user_id = session_history.creator.id
|
|
music_session.band_id = session_history.band.id unless session_history.band.nil?
|
|
session_history.save!
|
|
end
|
|
end
|
|
end
|