2012-11-16 02:08:37 +00:00
|
|
|
module JamRuby
|
|
|
|
|
class Recording < ActiveRecord::Base
|
2013-01-30 05:46:40 +00:00
|
|
|
|
2012-11-16 02:08:37 +00:00
|
|
|
self.primary_key = 'id'
|
|
|
|
|
|
2013-01-22 22:03:23 +00:00
|
|
|
has_and_belongs_to_many :users, :class_name => "JamRuby::User"
|
2013-01-30 05:46:40 +00:00
|
|
|
belongs_to :owner, :class_name => "JamRuby::User", :inverse_of => :owned_recordings
|
|
|
|
|
belongs_to :band, :class_name => "JamRuby::Band", :inverse_of => :recordings
|
2013-01-24 01:48:13 +00:00
|
|
|
belongs_to :music_session, :class_name => "JamRuby::MusicSession", :inverse_of => :recording
|
2013-04-13 00:16:40 +00:00
|
|
|
has_one :mix, :class_name => "JamRuby::Mix", :inverse_of => :recording
|
2013-01-22 19:15:52 +00:00
|
|
|
|
|
|
|
|
has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id
|
2012-11-16 02:08:37 +00:00
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
# genres
|
|
|
|
|
has_and_belongs_to_many :genres, :class_name => "JamRuby::Genre", :join_table => "recordings_genres"
|
|
|
|
|
|
2012-11-21 19:48:39 +00:00
|
|
|
# favorites
|
2012-12-04 03:39:57 +00:00
|
|
|
has_many :favorites, :class_name => "JamRuby::UserFavorite", :foreign_key => "recording_id"
|
|
|
|
|
has_many :inverse_favorites, :through => :favorites, :source => :recording, :class_name => "JamRuby::Recording"
|
2013-01-31 08:25:07 +00:00
|
|
|
|
2013-02-04 19:12:20 +00:00
|
|
|
validates :name, length: { maximum: 100 }
|
2013-01-31 08:25:07 +00:00
|
|
|
validates :description, length: { maximum: 200 }
|
|
|
|
|
validates :genres, length: { maximum: 3 }
|
2012-11-21 19:48:39 +00:00
|
|
|
|
2012-12-04 03:39:57 +00:00
|
|
|
def favorite_count
|
|
|
|
|
return self.favorites.size
|
|
|
|
|
end
|
|
|
|
|
|
2013-02-05 02:07:08 +00:00
|
|
|
def self.user_recordings(user_id)
|
|
|
|
|
query = Recording
|
|
|
|
|
.joins(
|
|
|
|
|
%Q{
|
|
|
|
|
INNER JOIN
|
|
|
|
|
recordings_users
|
|
|
|
|
ON
|
|
|
|
|
recordings_users.recording_id = recordings.id
|
|
|
|
|
}
|
|
|
|
|
)
|
2013-04-13 00:16:40 +00:00
|
|
|
.joins(
|
|
|
|
|
%Q{
|
|
|
|
|
LEFT OUTER JOIN
|
|
|
|
|
mixes
|
|
|
|
|
ON
|
|
|
|
|
recordings.id = mixes.recording_id
|
|
|
|
|
}
|
|
|
|
|
)
|
2013-02-05 02:07:08 +00:00
|
|
|
.order(
|
|
|
|
|
%Q{
|
|
|
|
|
recordings.created_at DESC
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
.where(
|
|
|
|
|
%Q{
|
|
|
|
|
recordings_users.user_id = '#{user_id}'
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
query
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-22 19:15:52 +00:00
|
|
|
# Start recording a session.
|
2013-02-04 19:12:20 +00:00
|
|
|
def self.start(music_session_id, owner)
|
2013-01-30 05:46:40 +00:00
|
|
|
|
|
|
|
|
recording = nil
|
|
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
# Use a transaction and lock to avoid races.
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
music_session = MusicSession.find(music_session_id, :lock => true)
|
2013-01-22 19:15:52 +00:00
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
if music_session.nil?
|
|
|
|
|
raise PermissionError, "the session has ended"
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-31 08:25:07 +00:00
|
|
|
unless music_session.recording.nil?
|
2013-01-22 19:15:52 +00:00
|
|
|
raise PermissionError, "the session is already being recorded"
|
2013-01-24 01:48:13 +00:00
|
|
|
end
|
2013-01-22 19:15:52 +00:00
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
recording = Recording.new
|
|
|
|
|
recording.music_session = music_session
|
2013-01-30 05:46:40 +00:00
|
|
|
recording.owner = owner
|
2013-01-31 08:25:07 +00:00
|
|
|
recording.is_public = false
|
|
|
|
|
recording.is_downloadable = false
|
2013-01-24 01:48:13 +00:00
|
|
|
|
|
|
|
|
music_session.connections.each do |connection|
|
|
|
|
|
recording.users << connection.user
|
|
|
|
|
connection.tracks.each do |track|
|
|
|
|
|
RecordedTrack.create_from_track(track, recording)
|
|
|
|
|
end
|
2013-01-22 19:15:52 +00:00
|
|
|
end
|
2013-01-22 22:03:23 +00:00
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
music_session.genres.each do |genre|
|
|
|
|
|
recording.genres << genre
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# Note that I believe this can be nil.
|
2013-01-30 05:46:40 +00:00
|
|
|
recording.band = music_session.band
|
2013-01-24 01:48:13 +00:00
|
|
|
recording.save
|
|
|
|
|
|
2013-01-30 05:46:40 +00:00
|
|
|
music_session.recording = recording
|
2013-01-24 01:48:13 +00:00
|
|
|
music_session.save
|
2013-01-22 22:03:23 +00:00
|
|
|
end
|
2013-01-30 05:46:40 +00:00
|
|
|
|
2013-01-30 17:57:12 +00:00
|
|
|
|
|
|
|
|
# FIXME:
|
|
|
|
|
# NEED TO SEND NOTIFICATION TO ALL USERS IN THE SESSION THAT RECORDING HAS STARTED HERE.
|
|
|
|
|
# I'LL STUB IT A BIT. NOTE THAT I REDO THE FIND HERE BECAUSE I DON'T WANT TO SEND THESE
|
|
|
|
|
# NOTIFICATIONS WHILE THE DB ROW IS LOCKED
|
|
|
|
|
music_session = MusicSession.find(music_session_id)
|
|
|
|
|
music_session.connections.each do |connection|
|
|
|
|
|
# connection.notify_recording_has_started
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-30 05:46:40 +00:00
|
|
|
recording
|
2013-01-22 19:15:52 +00:00
|
|
|
end
|
|
|
|
|
|
2013-01-24 01:48:13 +00:00
|
|
|
# Stop recording a session
|
2013-02-04 19:12:20 +00:00
|
|
|
# FIXME: What to do about recordings which are started and then stopped but never get any metadata (not even a name)?
|
|
|
|
|
# I'm guessing they should be deleted eventually.
|
2013-01-24 01:48:13 +00:00
|
|
|
def stop
|
|
|
|
|
# Use a transaction and lock to avoid races.
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
music_session = MusicSession.find(self.music_session_id, :lock => true)
|
|
|
|
|
if music_session.nil?
|
|
|
|
|
raise PermissionError, "the session has ended"
|
|
|
|
|
end
|
|
|
|
|
unless music_session.recording
|
|
|
|
|
raise PermissionError, "the session is not currently being recorded"
|
|
|
|
|
end
|
2013-01-30 05:46:40 +00:00
|
|
|
music_session.recording = nil
|
2013-01-24 01:48:13 +00:00
|
|
|
music_session.save
|
|
|
|
|
end
|
|
|
|
|
end
|
2013-01-30 17:57:12 +00:00
|
|
|
|
2013-02-04 19:12:20 +00:00
|
|
|
# Update the metadata for the recording.
|
2013-01-31 08:25:07 +00:00
|
|
|
def update_fields(params)
|
|
|
|
|
unless self.music_session.nil?
|
|
|
|
|
raise PermissionError, "recording data cannot be changed while it is being recorded"
|
|
|
|
|
end
|
2013-02-04 19:12:20 +00:00
|
|
|
|
|
|
|
|
if params[:name].nil?
|
|
|
|
|
raise PermissionError, "recording must have a name" if self.name.nil?
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-31 08:25:07 +00:00
|
|
|
self.name = params[:name] unless params[:name].nil?
|
|
|
|
|
self.description = params[:description] unless params[:description].nil?
|
|
|
|
|
|
|
|
|
|
genres = params[:genres]
|
2013-01-30 17:57:12 +00:00
|
|
|
unless genres.nil?
|
2013-01-31 08:25:07 +00:00
|
|
|
validate_genres(genres)
|
2013-01-30 17:57:12 +00:00
|
|
|
self.genres = []
|
|
|
|
|
genres.each do |genre_id|
|
|
|
|
|
g = Genre.find(genre_id)
|
|
|
|
|
self.genres << g
|
|
|
|
|
end
|
|
|
|
|
end
|
2013-01-31 08:25:07 +00:00
|
|
|
|
|
|
|
|
self.is_public = params[:is_public] unless params[:is_public].nil?
|
|
|
|
|
self.is_downloadable = params[:is_downloadable] unless params[:is_downloadable].nil?
|
|
|
|
|
|
2013-01-30 17:57:12 +00:00
|
|
|
save
|
|
|
|
|
end
|
2013-01-22 19:15:52 +00:00
|
|
|
|
2013-02-05 02:07:08 +00:00
|
|
|
# Find out if all the tracks for this recording have been uploaded
|
|
|
|
|
def uploaded?
|
|
|
|
|
self.recorded_tracks.each do |recorded_track|
|
|
|
|
|
return false unless recorded_track.fully_uploaded
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-14 04:50:38 +00:00
|
|
|
def self.search(query, options = { :limit => 10 })
|
|
|
|
|
|
|
|
|
|
# only issue search if at least 2 characters are specified
|
|
|
|
|
if query.nil? || query.length < 2
|
|
|
|
|
return []
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# create 'anded' statement
|
|
|
|
|
query = Search.create_tsquery(query)
|
|
|
|
|
|
|
|
|
|
if query.nil? || query.length == 0
|
|
|
|
|
return []
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return Recording.where("description_tsv @@ to_tsquery('jamenglish', ?)", query).limit(options[:limit])
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-22 19:15:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
def self.save(id, is_public, description, genres, updater_id, owner_id, is_band)
|
2013-01-30 05:46:40 +00:00
|
|
|
return nil
|
2013-01-22 19:15:52 +00:00
|
|
|
# Spec: https://jamkazam.atlassian.net/wiki/display/PS/Product+Specification+-+Studio
|
|
|
|
|
# This is seriously wrong. A recording needs to be created from inside a session. I'm not sure who owns
|
|
|
|
|
# the recording, but I do know that it's affiliated with the session and then should be able to get the band id
|
|
|
|
|
# and probably all this other stuff (genre, etc) from that. I need to read the recording spec in more detail
|
|
|
|
|
# to figure that out. I'll read it on bart.
|
|
|
|
|
#
|
|
|
|
|
# The studio spec is the key here. A couple notes:
|
|
|
|
|
# * Multiple musicians are all associated with a recording -- everyone who is in the music session when the recording starts
|
|
|
|
|
# * Associating a band with the recording is optional
|
|
|
|
|
# * The recording needs to be associated with a music_session for sure. Probably also a set of tracks (NOT musicians). Then, on
|
|
|
|
|
# recording completion is when you have the track -> saved_track (rename this to recorded_track) transition.
|
|
|
|
|
# * The metadata in general is filled in *after* the recording ends. This is important because it means the save method below
|
|
|
|
|
# is sort of jacked.
|
2013-01-30 05:46:40 +00:00
|
|
|
=begin
|
2012-11-22 08:27:23 +00:00
|
|
|
creator = User.find(updater_id)
|
|
|
|
|
|
|
|
|
|
if is_band
|
|
|
|
|
band = Band.find(owner_id)
|
|
|
|
|
validate_user_is_band_member(creator, band)
|
|
|
|
|
else
|
|
|
|
|
user = User.find(owner_id)
|
|
|
|
|
validate_user_is_creator(user, creator)
|
|
|
|
|
validate_user_is_musician(user)
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-21 19:48:39 +00:00
|
|
|
if id.nil?
|
2012-12-02 07:06:51 +00:00
|
|
|
validate_genres(genres, false)
|
2012-11-21 19:48:39 +00:00
|
|
|
recording = Recording.new()
|
2012-11-22 08:27:23 +00:00
|
|
|
recording.creator_id = updater_id
|
2012-11-21 19:48:39 +00:00
|
|
|
else
|
2012-12-02 07:06:51 +00:00
|
|
|
validate_genres(genres, true)
|
2012-11-21 19:48:39 +00:00
|
|
|
recording = Recording.find(id)
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
recording.updater_id = updater_id
|
|
|
|
|
|
2012-11-21 19:48:39 +00:00
|
|
|
# public flag
|
|
|
|
|
unless is_public.nil?
|
|
|
|
|
recording.public = is_public
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# description
|
|
|
|
|
unless description.nil?
|
|
|
|
|
recording.description = description
|
|
|
|
|
end
|
|
|
|
|
|
2012-12-02 07:06:51 +00:00
|
|
|
# genres
|
|
|
|
|
unless genres.nil?
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
# delete all genres for this recording first
|
|
|
|
|
unless recording.id.nil? || recording.id.length == 0
|
|
|
|
|
recording.genres.delete_all
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# loop through each genre in the array and save to the db
|
|
|
|
|
genres.each do |genre_id|
|
|
|
|
|
g = Genre.find(genre_id)
|
|
|
|
|
recording.genres << g
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
recording.updated_at = Time.now.getutc
|
|
|
|
|
|
|
|
|
|
# TODO: wrap in transaction with statements below
|
|
|
|
|
recording.save
|
|
|
|
|
|
2012-11-24 18:22:44 +00:00
|
|
|
if id.nil?
|
|
|
|
|
if is_band
|
|
|
|
|
recording.band_recordings << BandRecording.create(band_id: owner_id, recording_id: recording.id)
|
|
|
|
|
else
|
|
|
|
|
recording.musician_recordings << MusicianRecording.create(user_id: owner_id, recording_id: recording.id)
|
|
|
|
|
end
|
2012-11-21 19:48:39 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return recording
|
2013-01-30 05:46:40 +00:00
|
|
|
=end
|
2012-11-21 19:48:39 +00:00
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
private
|
|
|
|
|
def self.validate_user_is_band_member(user, band)
|
|
|
|
|
unless band.users.exists? user
|
2012-11-24 18:22:44 +00:00
|
|
|
raise PermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
|
2012-11-22 08:27:23 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.validate_user_is_creator(user, creator)
|
|
|
|
|
unless user.id == creator.id
|
2012-11-24 18:22:44 +00:00
|
|
|
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
2012-11-22 08:27:23 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.validate_user_is_musician(user)
|
|
|
|
|
unless user.musician?
|
2012-11-24 18:22:44 +00:00
|
|
|
raise PermissionError, ValidationMessages::USER_NOT_MUSICIAN_VALIDATION_ERROR
|
2012-11-22 08:27:23 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2013-01-31 08:25:07 +00:00
|
|
|
def validate_genres(genres)
|
|
|
|
|
if genres.length < Limits::MIN_GENRES_PER_RECORDING
|
2012-12-02 07:06:51 +00:00
|
|
|
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_MINIMUM_NOT_MET
|
2013-01-31 08:25:07 +00:00
|
|
|
end
|
2012-12-02 07:06:51 +00:00
|
|
|
|
2013-01-31 08:25:07 +00:00
|
|
|
if genres.length > Limits::MAX_GENRES_PER_RECORDING
|
|
|
|
|
raise JamRuby::JamArgumentError, ValidationMessages::GENRE_LIMIT_EXCEEDED
|
2012-12-02 07:06:51 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-11-22 08:27:23 +00:00
|
|
|
=begin
|
2012-11-21 19:48:39 +00:00
|
|
|
def self.delete(id, owner_id, is_band)
|
|
|
|
|
if is_band?
|
2012-11-22 08:27:23 +00:00
|
|
|
JamRuby::Recording.delete_all "(user_id = '#{user_id}' AND follower_id = '#{follower_id}')"
|
2012-11-21 19:48:39 +00:00
|
|
|
else
|
|
|
|
|
end
|
|
|
|
|
end
|
2012-11-22 08:27:23 +00:00
|
|
|
=end
|
2012-11-16 02:08:37 +00:00
|
|
|
end
|
2013-01-22 22:03:23 +00:00
|
|
|
end
|