merge conflicts

This commit is contained in:
Jonathan Kolyer 2014-01-08 18:45:34 -06:00
commit e5d23cc3bd
198 changed files with 7520 additions and 2142 deletions

View File

@ -49,7 +49,7 @@ gem 'aasm', '3.0.16'
gem 'postgres-copy', '0.6.0'
gem 'aws-sdk', '1.29.1'
gem 'bugsnag'
gem 'resque'
gem 'eventmachine', '1.0.3'
gem 'amqp', '0.9.8'

View File

@ -9,17 +9,21 @@ if [ "$?" = "0" ]; then
echo "build succeeded"
if [ ! -z "$PACKAGE" ]; then
echo "publishing ubuntu package (.deb)"
DEBPATH=`find target/deb -name *.deb`
DEBNAME=`basename $DEBPATH`
if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* ]]; then
echo "publishing ubuntu package (.deb)"
DEBPATH=`find target/deb -name *.deb`
DEBNAME=`basename $DEBPATH`
curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME
curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME
if [ "$?" != "0" ]; then
echo "deb publish failed"
exit 1
if [ "$?" != "0" ]; then
echo "deb publish failed"
exit 1
fi
echo "done publishing deb"
else
echo "Skipping publish since branch is neither master or develop..."
fi
echo "done publishing deb"
fi
else
echo "build failed"

View File

@ -1 +1 @@
ruby-2.0.0-p247
2.0.0-p247

View File

@ -7,38 +7,39 @@ echo "starting build..."
./build
if [ "$?" = "0" ]; then
echo "build succeeded"
echo "publishing gem"
pushd "target/ruby_package"
find . -name *.gem -exec curl -f -T {} $GEM_SERVER/{} \;
if [ "$?" != "0" ]; then
echo "publish failed"
exit 1
fi
popd
echo "done publishing gems"
echo "build succeeded"
if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* ]]; then
echo "publishing gem"
pushd "target/ruby_package"
find . -name *.gem -exec curl -f -T {} $GEM_SERVER/{} \;
if [ ! -z "$PACKAGE" ]; then
echo "publishing ubuntu packages (.deb)"
for f in `find target -name '*.deb'`; do
DEBNAME=`basename $f`
DEBPATH="$f"
echo "publishing $DEBPATH to deb server"
curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME
if [ "$?" != "0" ]; then
echo "deb publish failed of $DEBPATH"
exit 1
fi
done
if [ "$?" != "0" ]; then
echo "publish failed"
exit 1
fi
echo "done publishing debs"
popd
echo "done publishing gems"
if [ ! -z "$PACKAGE" ]; then
echo "publishing ubuntu packages (.deb)"
for f in `find target -name '*.deb'`; do
DEBNAME=`basename $f`
DEBPATH="$f"
echo "publishing $DEBPATH to deb server"
curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME
if [ "$?" != "0" ]; then
echo "deb publish failed of $DEBPATH"
exit 1
fi
done
echo "done publishing debs"
fi
else
echo "Skipping publish since branch is neither master or develop..."
fi
else
echo "build failed"
exit 1
fi

View File

@ -81,5 +81,8 @@ notification_band_invite.sql
band_photo_filepicker.sql
bands_geocoding.sql
store_s3_filenames.sql
discardable_recorded_tracks.sql
music_sessions_have_claimed_recording.sql
discardable_recorded_tracks2.sql
icecast.sql
home_page_promos.sql

View File

@ -0,0 +1,5 @@
-- there are no valid recordings and mixes at this time
DELETE FROM recorded_tracks;
DELETE FROM mixes;
ALTER TABLE recorded_tracks ADD COLUMN discard BOOLEAN DEFAULT FALSE NOT NULL;

View File

@ -0,0 +1,2 @@
ALTER TABLE recorded_tracks ALTER COLUMN discard DROP DEFAULT;
ALTER TABLE recorded_tracks ALTER COLUMN discard DROP NOT NULL;

305
db/up/icecast.sql Normal file
View File

@ -0,0 +1,305 @@
-- see http://www.icecast.org/docs/icecast-2.3.3/icecast2_config_file.html#limits
CREATE TABLE icecast_limits (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- number of listening clients
clients INTEGER NOT NULL DEFAULT 1000,
--number of sources include souce clients and relays
sources INTEGER NOT NULL DEFAULT 50,
-- maximum size (in bytes) of the stream queue
queue_size INTEGER NOT NULL DEFAULT 102400,
-- does not appear to be used
client_timeout INTEGER DEFAULT 10,
-- The maximum time (in seconds) to wait for a request to come in once
-- the client has made a connection to the server.
-- In general this value should not need to be tweaked.
header_timeout INTEGER DEFAULT 15,
-- If a connected source does not send any data within this
-- timeout period (in seconds), then the source connection
-- will be removed from the server.
source_timeout INTEGER DEFAULT 10,
-- The burst size is the amount of data (in bytes)
-- to burst to a client at connection time.
burst_size INTEGER DEFAULT 65536,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_admin_authentications (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- The unencrypted password used by sources to connect to icecast2.
-- The default username for all source connections is 'source' but
-- this option allows to specify a default password. This and the username
-- can be changed in the individual mount sections.
source_password VARCHAR NOT NULL DEFAULT 'icejam321',
-- Used in the master server as part of the authentication when a slave requests
-- the list of streams to relay. The default username is 'relay'
relay_user VARCHAR NOT NULL DEFAULT 'relay',
relay_password VARCHAR NOT NULL DEFAULT 'jkrelayhack',
--The username/password used for all administration functions.
admin_user VARCHAR NOT NULL DEFAULT 'jkadmin',
admin_password VARCHAR NOT NULL DEFAULT 'jKadmin123',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
--contains all the settings for listing a stream on any of the Icecast2 YP Directory servers.
-- Multiple occurances of this section can be specified in order to be listed on multiple directory servers.
create table icecast_directorys (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
yp_url_timeout integer not null default 15,
yp_url character not null UNIQUE default 'http://dir.xiph.org/cgi-bin/yp-cgi',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_servermiscs (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- This is the DNS name or IP address that will be used for the stream directory lookups or possibily
-- the playlist generation if a Host header is not provided. While localhost is shown as an example,
-- in fact you will want something that your listeners can use.
hostname character not null default 'concertsvr.jamkazam.com',
--This sets the location string for this icecast instance. It will be shown e.g in the web interface.
location character not null default 'earth',
--This should contain contact details for getting in touch with the server administrator.
admin character not null default 'icemaster@localhost',
-- This flag turns on the icecast2 fileserver from which static files can be served.
-- All files are served relative to the path specified in the <paths><webroot> configuration
-- setting. By default the setting is enabled so that requests for the images
-- on the status page are retrievable.
fileserve INTEGER not null default 1,
-- This optional setting allows for the administrator of the server to override the
-- default server identification. The default is icecast followed by a version number
-- and most will not care to change it however this setting will change that.
server_id character not null default 'icecast 2.3',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_listen_sockets (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- The TCP port that will be used to accept client connections.
port integer not null default 8001,
-- An optional IP address that can be used to bind to a specific network card.
-- If not supplied, then it will bind to all interfaces.
bind_address character,
shoutcast_mount character default NULL,
shoutcast_compat INTEGER not null default 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_mastersvr_relays (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- ip address of the master icecast server and port number
master_server character not null,
master_server_port integer not null,
--The interval (in seconds) that the Relay Server will poll the Master Server for any new mountpoints to relay.
master_update_interval integer not null default 120,
-- This is the relay username on the master server. It is used to query the server for a list of
-- mountpoints to relay. If not specified then 'relay' is used
master_username character not null default 'relay',
master_password character not null,
--Global on-demand setting for relays. Because you do not have individual relay options when
-- using a master server relay, you still may want those relays to only pull the stream when
-- there is at least one listener on the slave. The typical case here is to avoid surplus
-- bandwidth costs when no one is listening.
relays_on_demand INTEGER default 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
--make sure this combo is unique
--CONSTRAINT serverID UNIQUE KEY (master_server,master_server_port)
);
create table icecast_relays (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- ip address of server we are relaying from and port number
server character not null,
port integer not null default 8001,
-- mount at server. eg /example.ogg
mount character not null,
-- eg /different.ogg
local_mount character not null,
-- eg joe. could be null
username character default NULL ,
-- user password
password character default null ,
relay_shoutcast_metadata INTEGER default 0,
--- relay only if we have someone wanting to listen
on_demand INTEGER default 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create TABLE icecast_user_authentications(
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
--"htpasswd or url"
type CHARACTER DEFAULT NULL ,
-- these are for httpasswd
filename CHARACTER default NULL,
allow_duplicate_users INTEGER DEFAULT 0,
-- these options are for url
-- eg value="http://myauthserver.com/stream_start.php"
mount_add CHARACTER default NULL,
--value="http://myauthserver.com/stream_end.php"
mount_remove CHARACTER default NULL,
--value="http://myauthserver.com/listener_joined.php"
listener_add CHARACTER default NULL,
--value="http://myauthserver.com/listener_left.php"
listener_remove CHARACTER default NULL,
-- value="user"
username CHARACTER default NULL,
-- value="pass"
password CHARACTER default NULL,
-- value="icecast-auth-user: 1"
auth_header CHARACTER default NULL,
-- value="icecast-auth-timelimit:"
timelimit_header CHARACTER default NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_mounts (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
-- eg/example-complex.ogg
mount_name CHARACTER UNIQUE NOT NULL,
username CHARACTER NOT NULL DEFAULT 'jamsource',
password CHARACTER NOT NULL DEFAULT 'jamksource',
max_listeners INTEGER NOT NULL DEFAULT 4,
max_listener_duration INTEGER NOT NULL DEFAULT 3600,
-- dump of the stream coming through on this mountpoint.
-- eg /tmp/dump-example1.ogg
dump_file CHARACTER DEFAULT NULL,
-- intro music to play
-- This optional value specifies a mountpoint that clients are automatically moved to
-- if the source shuts down or is not streaming at the time a listener connects.
intro CHARACTER NOT NULL DEFAULT '/intro.ogg',
fallback_mount CHARACTER NOT NULL DEFAULT '/sourcedown.ogg',
-- When enabled, this allows a connecting source client or relay on this mountpoint
-- to move listening clients back from the fallback mount.
fallback_override INTEGER DEFAULT 1,
-- When set to 1, this will cause new listeners, when the max listener count for the mountpoint
-- has been reached, to move to the fallback mount if there is one specified.
fallback_when_full INTEGER DEFAULT 1,
--For non-Ogg streams like MP3, the metadata that is inserted into the stream often
-- has no defined character set.
charset CHARACTER NOT NULL DEFAULT 'ISO8859-1',
-- possilble values are -1, 0, 1
public INTEGER DEFAULT 1,
stream_name VARCHAR NOT NULL DEFAULT 'My Jamkazam Audio Stream',
stream_description VARCHAR NOT NULL DEFAULT 'My JK audio description',
-- direct to user page
stream_url CHARACTER NOT NULL DEFAULT 'http://wwww.jamakazam.com#user_id',
-- get this from the session info
genre VARCHAR NOT NULL DEFAULT 'Unknown',
bitrate integer NOT NULL default 92,
type CHARACTER NOT NULL DEFAULT 'application/ogg' ,
subtype CHARACTER NOT NULL DEFAULT 'vorbis',
-- Enable this to prevent this mount from being shown on the xsl pages.
-- This is mainly for cases where a local relay is configured and you do
-- not want the source of the local relay to be shown
hidden INTEGER DEFAULT 1,
-- This optional setting allows for providing a burst size which overrides the
-- default burst size as defined in limits. The value is in bytes.
burst_size INTEGER DEFAULT 65536,
mp3_metadata_interval INTEGER DEFAULT 4096,
--called when the source connects or disconnects. The scripts are called with the name of the mount
on_connect CHARACTER DEFAULT '/home/icecast/bin/source-start',
on_disconnect CHARACTER DEFAULT '/home/icecast/bin/source-end',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
auth_id VARCHAR(64) NOT NULL REFERENCES icecast_user_authentications(id)
);
create table icecast_paths (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
basedir CHARACTER NOT NULL DEFAULT './',
logdir CHARACTER NOT NULL DEFAULT './logs',
pidfile CHARACTER NOT NULL DEFAULT './icecast.pid',
webroot CHARACTER NOT NULL DEFAULT './web',
adminroot CHARACTER NOT NULL DEFAULT './admin',
allow_ip CHARACTER NOT NULL DEFAULT '/path/to/ip_allowlist',
deny_ip CHARACTER NOT NULL DEFAULT '/path_to_ip_denylist',
alias CHARACTER DEFAULT 'source="/foo" dest="/bar"',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_loggings (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
accesslog CHARACTER NOT NULL DEFAULT 'access.log',
errorlog CHARACTER NOT NULL DEFAULT 'error.log',
playlistlog CHARACTER NOT NULL DEFAULT 'playlist.log',
-- 4 Debug, 3 Info, 2 Warn, 1 Error
loglevel INTEGER NOT NULL DEFAULT 4 ,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create table icecast_securitys (
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
chroot INTEGER NOT NULL DEFAULT 0,
changeowner_user CHARACTER DEFAULT 'nobody',
changeowner_group CHARACTER DEFAULT 'nogroup',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create TABLE icecast_servers(
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
icecast_limit_id VARCHAR(64) REFERENCES icecast_limits(id)
-- configs
-- mounts
);

View File

@ -0,0 +1,3 @@
-- let a music_session reference a claimed recording, so that the state of the session knows if someone is playing a recording back
ALTER TABLE music_sessions ADD COLUMN claimed_recording_id VARCHAR(64) REFERENCES claimed_recordings(id);
ALTER TABLE music_sessions ADD COLUMN claimed_recording_initiator_id VARCHAR(64) REFERENCES users(id);

View File

@ -24,4 +24,5 @@ ALTER TABLE recorded_tracks ADD COLUMN client_id VARCHAR(64) NOT NULL;
ALTER TABLE recorded_tracks ADD COLUMN track_id VARCHAR(64) NOT NULL;
-- so that server can correlate to client track
DELETE FROM tracks;
ALTER TABLE tracks ADD COLUMN client_track_id VARCHAR(64) NOT NULL;

View File

@ -1 +1 @@
ruby-2.0.0-p247
2.0.0-p247

View File

@ -9,43 +9,62 @@ package jampb;
message ClientMessage {
enum Type {
LOGIN = 100;
LOGIN_ACK = 101;
LOGIN = 100;
LOGIN_ACK = 105;
LOGIN_MUSIC_SESSION = 110;
LOGIN_MUSIC_SESSION_ACK = 115;
LEAVE_MUSIC_SESSION = 120;
LEAVE_MUSIC_SESSION_ACK = 125;
HEARTBEAT = 130;
HEARTBEAT_ACK = 135;
LOGIN_MUSIC_SESSION = 102;
LOGIN_MUSIC_SESSION_ACK = 103;
FRIEND_SESSION_JOIN = 104;
LEAVE_MUSIC_SESSION = 105;
LEAVE_MUSIC_SESSION_ACK = 106;
HEARTBEAT = 107;
FRIEND_UPDATE = 108;
SESSION_INVITATION = 109;
MUSICIAN_SESSION_DEPART = 110;
JOIN_REQUEST = 111;
FRIEND_REQUEST = 112;
FRIEND_REQUEST_ACCEPTED = 113;
MUSICIAN_SESSION_JOIN = 114;
MUSICIAN_SESSION_FRESH = 115;
MUSICIAN_SESSION_STALE = 116;
HEARTBEAT_ACK = 117;
JOIN_REQUEST_APPROVED = 118;
JOIN_REQUEST_REJECTED = 119;
BAND_INVITATION = 120;
BAND_INVITATION_ACCEPTED = 121;
// friend notifications
FRIEND_UPDATE = 140;
FRIEND_REQUEST = 145;
FRIEND_REQUEST_ACCEPTED = 150;
FRIEND_SESSION_JOIN = 155;
NEW_USER_FOLLOWER = 160;
NEW_BAND_FOLLOWER = 161;
TEST_SESSION_MESSAGE = 200;
// session invitations
SESSION_INVITATION = 165;
SESSION_ENDED = 170;
JOIN_REQUEST = 175;
JOIN_REQUEST_APPROVED = 180;
JOIN_REQUEST_REJECTED = 185;
SESSION_JOIN = 190;
SESSION_DEPART = 195;
MUSICIAN_SESSION_JOIN = 196;
// recording notifications
MUSICIAN_RECORDING_SAVED = 200;
BAND_RECORDING_SAVED = 205;
RECORDING_STARTED = 210;
RECORDING_ENDED = 215;
RECORDING_MASTER_MIX_COMPLETE = 220;
DOWNLOAD_AVAILABLE = 221;
// band notifications
BAND_INVITATION = 225;
BAND_INVITATION_ACCEPTED = 230;
BAND_SESSION_JOIN = 235;
MUSICIAN_SESSION_FRESH = 240;
MUSICIAN_SESSION_STALE = 245;
TEST_SESSION_MESSAGE = 295;
PING_REQUEST = 300;
PING_ACK = 301;
PEER_MESSAGE = 302;
TEST_CLIENT_MESSAGE = 303;
PING_ACK = 305;
PEER_MESSAGE = 310;
TEST_CLIENT_MESSAGE = 315;
SERVER_BAD_STATE_RECOVERED = 900;
SERVER_GENERIC_ERROR = 1000;
SERVER_REJECTION_ERROR = 1001;
SERVER_PERMISSION_ERROR = 1002;
SERVER_BAD_STATE_ERROR = 1003;
SERVER_REJECTION_ERROR = 1005;
SERVER_PERMISSION_ERROR = 1010;
SERVER_BAD_STATE_ERROR = 1015;
}
// Identifies which inner message is filled in
@ -59,45 +78,65 @@ message ClientMessage {
// Client-Server messages (to/from)
optional Login login = 100; // to server
optional LoginAck login_ack = 101; // from server
optional LoginMusicSession login_music_session = 102; // to server
optional LoginMusicSessionAck login_music_session_ack = 103; // from server
optional FriendSessionJoin friend_session_join = 104; // from server to all members
optional LeaveMusicSession leave_music_session = 105;
optional LeaveMusicSessionAck leave_music_session_ack = 106;
optional Heartbeat heartbeat = 107;
optional FriendUpdate friend_update = 108; // from server to all friends of user
optional SessionInvitation session_invitation = 109; // from server to user
optional MusicianSessionDepart musician_session_depart = 110;
optional JoinRequest join_request = 111;
optional FriendRequest friend_request = 112;
optional FriendRequestAccepted friend_request_accepted = 113;
optional MusicianSessionJoin musician_session_join = 114;
optional MusicianSessionFresh musician_session_fresh = 115;
optional MusicianSessionStale musician_session_stale = 116;
optional HeartbeatAck heartbeat_ack = 117;
optional JoinRequestApproved join_request_approved = 118;
optional JoinRequestRejected join_request_rejected = 119;
optional BandInvitation band_invitation = 120;
optional BandInvitationAccepted band_invitation_accepted = 121;
optional LoginAck login_ack = 105; // from server
optional LoginMusicSession login_music_session = 110; // to server
optional LoginMusicSessionAck login_music_session_ack = 115; // from server
optional LeaveMusicSession leave_music_session = 120;
optional LeaveMusicSessionAck leave_music_session_ack = 125;
optional Heartbeat heartbeat = 130;
optional HeartbeatAck heartbeat_ack = 135;
// friend notifications
optional FriendUpdate friend_update = 140; // from server to all friends of user
optional FriendRequest friend_request = 145;
optional FriendRequestAccepted friend_request_accepted = 150;
optional NewUserFollower new_user_follower = 160;
optional NewBandFollower new_band_follower = 161;
// session invitations
optional SessionInvitation session_invitation = 165; // from server to user
optional SessionEnded session_ended = 170;
optional JoinRequest join_request = 175;
optional JoinRequestApproved join_request_approved = 180;
optional JoinRequestRejected join_request_rejected = 185;
optional SessionJoin session_join = 190;
optional SessionDepart session_depart = 195;
optional MusicianSessionJoin musician_session_join = 196;
optional BandSessionJoin band_session_join = 197;
// recording notifications
optional MusicianRecordingSaved musician_recording_saved = 200;
optional BandRecordingSaved band_recording_saved = 205;
optional RecordingStarted recording_started = 210;
optional RecordingEnded recording_ended = 215;
optional RecordingMasterMixComplete recording_master_mix_complete = 220;
optional DownloadAvailable download_available = 221;
// band notifications
optional BandInvitation band_invitation = 225;
optional BandInvitationAccepted band_invitation_accepted = 230;
optional MusicianSessionFresh musician_session_fresh = 240;
optional MusicianSessionStale musician_session_stale = 245;
// Client-Session messages (to/from)
optional TestSessionMessage test_session_message = 200;
optional TestSessionMessage test_session_message = 295;
// Client-Client messages (to/from)
optional PingRequest ping_request = 300;
optional PingAck ping_ack = 301;
optional PeerMessage peer_message = 302;
optional TestClientMessage test_client_message = 303;
optional PingAck ping_ack = 305;
optional PeerMessage peer_message = 310;
optional TestClientMessage test_client_message = 315;
// Server-to-Client special messages
optional ServerBadStateRecovered server_bad_state_recovered = 900;
// Server-to-Client errors
optional ServerGenericError server_generic_error = 1000;
optional ServerRejectionError server_rejection_error = 1001;
optional ServerPermissionError server_permission_error = 1002;
optional ServerBadStateError server_bad_state_error = 1003;
optional ServerRejectionError server_rejection_error = 1005;
optional ServerPermissionError server_permission_error = 1010;
optional ServerBadStateError server_bad_state_error = 1015;
}
// route_to: server
@ -157,32 +196,161 @@ message LeaveMusicSessionAck {
optional string error_reason = 2;
}
// route_to: client:
// sent by server to let the rest of the participants know a user has joined.
message FriendSessionJoin {
optional string session_id = 1; // the session ID
optional string user_id = 2; // this is the user_id and can be used for user unicast messages
optional string username = 3; // meant to be a display name
optional string photo_url = 4;
message FriendUpdate {
optional string user_id = 1;
optional string photo_url = 2;
optional bool online = 3;
optional string msg = 4;
}
message FriendRequest {
optional string friend_request_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string notification_id = 4;
optional string created_at = 5;
}
message FriendRequestAccepted {
optional string photo_url = 1;
optional string msg = 2;
optional string notification_id = 3;
optional string created_at = 4;
}
message NewUserFollower {
optional string photo_url = 1;
optional string msg = 2;
optional string notification_id = 3;
optional string created_at = 4;
}
message NewBandFollower {
optional string photo_url = 1;
optional string msg = 2;
optional string notification_id = 3;
optional string created_at = 4;
}
message SessionInvitation {
optional string session_id = 1;
optional string msg = 2;
optional string notification_id = 3;
optional string created_at = 4;
}
message SessionEnded {
}
message JoinRequest {
optional string join_request_id = 1;
optional string session_id = 2;
optional string photo_url = 3;
optional string msg = 4;
optional string notification_id = 5;
optional string created_at = 6;
}
message JoinRequestApproved {
optional string join_request_id = 1;
optional string session_id = 2;
optional string photo_url = 3;
optional string msg = 4;
optional string notification_id = 5;
optional string created_at = 6;
}
message JoinRequestRejected {
optional string invitation_id = 1;
optional string session_id = 2;
optional string photo_url = 3;
optional string msg = 4;
optional string notification_id = 5;
optional string created_at = 6;
}
message SessionJoin {
optional string session_id = 1;
optional string photo_url = 2;
optional string msg = 3;
}
message SessionDepart {
optional string session_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string recording_id = 4;
}
// route_to: client:
// sent by server to let the rest of the participants know a user has joined.
message MusicianSessionJoin {
optional string session_id = 1; // the session ID
optional string user_id = 2; // this is the user_id and can be used for user unicast messages
optional string username = 3; // meant to be a display name
optional string photo_url = 4;
optional string session_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string notification_id = 4;
optional string created_at = 5;
}
// route_to: client:
// sent by server to let the rest of the participants know a user has left.
message MusicianSessionDepart {
optional string session_id = 1; // the session ID
optional string user_id = 2; // this is the user_id and can be used for user unicast messages
optional string username = 3; // meant to be a display name
optional string photo_url = 4;
optional string recordingId = 5; // if specified, the recording was stopped automatically
message BandSessionJoin {
optional string session_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string notification_id = 4;
optional string created_at = 5;
}
message MusicianRecordingSaved {
optional string recording_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string notification_id = 4;
optional string created_at = 5;
}
message BandRecordingSaved {
optional string recording_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string notification_id = 4;
optional string created_at = 5;
}
message RecordingStarted {
optional string photo_url = 1;
optional string msg = 2;
}
message RecordingEnded {
optional string photo_url = 1;
optional string msg = 2;
}
message RecordingMasterMixComplete {
optional string recording_id = 1;
optional string msg = 2;
optional string notification_id = 3;
optional string created_at = 4;
}
message DownloadAvailable {
}
message BandInvitation {
optional string band_invitation_id = 1;
optional string band_id = 2;
optional string photo_url = 3;
optional string msg = 4;
optional string notification_id = 5;
optional string created_at = 6;
}
message BandInvitationAccepted {
optional string band_invitation_id = 1;
optional string photo_url = 2;
optional string msg = 3;
optional string notification_id = 4;
optional string created_at = 5;
}
// route_to: client:
@ -203,59 +371,6 @@ message MusicianSessionStale {
optional string photo_url = 4;
}
message JoinRequest {
optional string join_request_id = 1;
optional string session_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
message JoinRequestApproved {
optional string join_request_id = 1;
optional string session_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
message JoinRequestRejected {
optional string invitation_id = 1;
optional string session_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
message BandInvitation {
optional string band_invitation_id = 1;
optional string band_id = 2;
optional string user_id = 3;
optional string username = 4;
optional string photo_url = 5;
optional string band_name = 6;
optional string msg = 7;
optional string notification_id = 8;
optional string created_at = 9;
}
message BandInvitationAccepted {
optional string band_invitation_id = 1;
optional string user_id = 2;
optional string username = 3;
optional string photo_url = 4;
optional string band_name = 5;
optional string msg = 6;
optional string notification_id = 7;
optional string created_at = 8;
}
// route_to: session
// a test message used by ruby-client currently. just gives way to send out to rest of session
message TestSessionMessage {
@ -298,57 +413,12 @@ message Heartbeat {
message HeartbeatAck {
}
// target: client
// send from server to client when user sends a friend request
message FriendRequest {
optional string friend_request_id = 1;
optional string user_id = 2;
optional string name = 3;
optional string photo_url = 4;
optional string friend_id = 5;
optional string msg = 6;
optional string notification_id = 7;
optional string created_at = 8;
}
// target: client
message FriendRequestAccepted {
optional string friend_id = 1; // accepter
optional string name = 2;
optional string photo_url = 3;
optional string user_id = 4; // original requester
optional string msg = 5;
optional string notification_id = 6;
optional string created_at = 7;
}
// target: client
// send from server to client when a user logs in
message FriendUpdate {
optional string user_id = 1;
optional string name = 2;
optional string photo_url = 3;
optional bool online = 4;
optional string msg = 5;
}
// route_to: user:[USER_ID]
// let a user know they've been invited to a session
message SessionInvitation {
optional string sender_name = 1;
optional string session_id = 2;
optional string notification_id = 3;
optional string created_at = 4;
}
// route_to: client
// this should follow a ServerBadStateError in the case that the
// websocket gateway recovers from whatever ailed it
message ServerBadStateRecovered {
}
// route_to: client
// this indicates unhandled error on server
// if you receive this, your connection will close after.

View File

@ -1 +1 @@
ruby-2.0.0-p247
2.0.0-p247

View File

@ -10,6 +10,7 @@ gem 'pg', '0.15.1', :platform => [:mri, :mswin, :mingw]
gem 'jdbc_postgres', :platform => [:jruby]
gem 'activerecord', '3.2.13'
gem "activerecord-import", "~> 0.4.1"
gem 'uuidtools', '2.1.2'
gem 'bcrypt-ruby', '3.0.1'
gem 'ruby-protocol-buffers', '1.2.2'
@ -23,7 +24,7 @@ gem 'carrierwave'
gem 'aasm', '3.0.16'
gem 'devise', '>= 1.1.2'
gem 'postgres-copy'
gem 'resque'
gem 'geokit-rails'
gem 'postgres_ext'

1
ruby/config/resque.yml Normal file
View File

@ -0,0 +1 @@
test: localhost:6379

View File

@ -2,7 +2,6 @@ require "pg"
require "active_record"
require "carrierwave"
require "carrierwave/orm/activerecord"
require "carrierwave_direct"
require "jampb"
require "uuidtools"
require "logging"
@ -14,6 +13,7 @@ require "sendgrid"
require "postgres-copy"
require "geokit-rails"
require "postgres_ext"
require 'builder'
require "jam_ruby/constants/limits"
require "jam_ruby/constants/notification_types"
@ -27,6 +27,7 @@ require "jam_ruby/lib/module_overrides"
require "jam_ruby/lib/s3_util"
require "jam_ruby/lib/s3_manager"
require "jam_ruby/lib/profanity"
require "jam_ruby/resque/audiomixer"
require "jam_ruby/mq_router"
require "jam_ruby/base_manager"
require "jam_ruby/connection_manager"
@ -84,7 +85,23 @@ require "jam_ruby/models/mix"
require "jam_ruby/models/claimed_recording"
require "jam_ruby/models/crash_dump"
require "jam_ruby/models/isp_score_batch"
<<<<<<< HEAD
require "jam_ruby/models/promotional"
=======
require "jam_ruby/models/icecast_admin_authentication"
require "jam_ruby/models/icecast_directory"
require "jam_ruby/models/icecast_limit"
require "jam_ruby/models/icecast_listen_socket"
require "jam_ruby/models/icecast_logging"
require "jam_ruby/models/icecast_mastersvr_relay"
require "jam_ruby/models/icecast_mount"
require "jam_ruby/models/icecast_path"
require "jam_ruby/models/icecast_relay"
require "jam_ruby/models/icecast_sercurity"
require "jam_ruby/models/icecast_server"
require "jam_ruby/models/icecast_servermisc"
require "jam_ruby/models/icecast_user_authentication"
>>>>>>> develop
include Jampb

View File

@ -88,5 +88,83 @@
end
end
#################################### NOTIFICATION EMAILS ####################################
def friend_request(email, msg)
subject = "You have a new friend request on JamKazam"
unique_args = {:type => "friend_request"}
send_notification(email, subject, msg, unique_args)
end
def friend_request_accepted(email, msg)
subject = "You have a new friend on JamKazam"
unique_args = {:type => "friend_request_accepted"}
send_notification(email, subject, msg, unique_args)
end
def new_user_follower(email, msg)
subject = "You have a new follower on JamKazam"
unique_args = {:type => "new_user_follower"}
send_notification(email, subject, msg, unique_args)
end
def new_band_follower(email, msg)
subject = "Your band has a new follower on JamKazam"
unique_args = {:type => "new_band_follower"}
send_notification(email, subject, msg, unique_args)
end
def session_invitation(email, msg)
subject = "You have been invited to a session on JamKazam"
unique_args = {:type => "session_invitation"}
send_notification(email, subject, msg, unique_args)
end
def musician_session_join(email, msg)
subject = "Someone you know is in a session on JamKazam"
unique_args = {:type => "musician_session_join"}
send_notification(email, subject, msg, unique_args)
end
def band_session_join(email, msg)
subject = "A band that you follow has joined a session"
unique_args = {:type => "band_session_join"}
send_notification(email, subject, msg, unique_args)
end
def musician_recording_saved(email, msg)
subject = msg
unique_args = {:type => "musician_recording_saved"}
send_notification(email, subject, msg, unique_args)
end
def band_recording_saved(email, msg)
subject = msg
unique_args = {:type => "band_recording_saved"}
send_notification(email, subject, msg, unique_args)
end
def band_invitation(email, msg)
subject = "You have been invited to join a band on JamKazam"
unique_args = {:type => "band_invitation"}
send_notification(email, subject, msg, unique_args)
end
def band_invitation_accepted(email, msg)
subject = "Your band invitation was accepted"
unique_args = {:type => "band_invitation_accepted"}
send_notification(email, subject, msg, unique_args)
end
def send_notification(email, subject, msg, unique_args)
@body = msg
sendgrid_category "Notification"
sendgrid_unique_args :type => unique_args[:type]
mail(:bcc => email, :subject => subject) do |format|
format.text
format.html
end
end
#############################################################################################
end
end

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New Band Invitation') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'Band Invitation Accepted') %>
<p><%= @body %></p>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New Band Recording') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New Band Session') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New JamKazam Friend Request') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'Friend Request Accepted') %>
<p><%= @body %></p>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New Musician Recording') %>
<p><%= @body %></p>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'Musician in Session') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New Band Follower on JamKazam') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'New Follower on JamKazam') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'Recording Master Mix Completed') %>
<p><%= @body %></p>

View File

@ -0,0 +1,3 @@
<% provide(:title, 'Session Invitation') %>
<p><%= @body %></p>

View File

@ -0,0 +1 @@
<%= @body %>

View File

@ -270,7 +270,14 @@ SQL
raise Exception, msg
end
end
else
# there are still people in the session
#ensure that there is no active claimed recording if the owner of that recording left the session
conn.exec("UPDATE music_sessions set claimed_recording_id = NULL, claimed_recording_initiator_id = NULL where claimed_recording_initiator_id = $1 and id = $2",
[user_id, previous_music_session_id])
end
end
end

View File

@ -5,23 +5,29 @@ module NotificationTypes
FRIEND_REQUEST = "FRIEND_REQUEST"
FRIEND_REQUEST_ACCEPTED = "FRIEND_REQUEST_ACCEPTED"
FRIEND_SESSION_JOIN = "FRIEND_SESSION_JOIN"
NEW_USER_FOLLOWER = "NEW_USER_FOLLOWER"
NEW_BAND_FOLLOWER = "NEW_BAND_FOLLOWER"
# session notifications
SESSION_INVITATION = "SESSION_INVITATION"
SESSION_ENDED = "SESSION_ENDED" # used to remove session-related notification from sidebar
SESSION_ENDED = "SESSION_ENDED" # used to remove session-related notifications from sidebar
JOIN_REQUEST = "JOIN_REQUEST"
JOIN_REQUEST_APPROVED = "JOIN_REQUEST_APPROVED"
JOIN_REQUEST_REJECTED = "JOIN_REQUEST_REJECTED"
# musician notifications
SESSION_JOIN = "SESSION_JOIN"
SESSION_DEPART = "SESSION_DEPART"
MUSICIAN_SESSION_JOIN = "MUSICIAN_SESSION_JOIN"
MUSICIAN_SESSION_DEPART = "MUSICIAN_SESSION_DEPART"
# recording notifications
RECORDING_CREATED = "RECORDING_CREATED"
MUSICIAN_RECORDING_SAVED = "MUSICIAN_RECORDING_SAVED"
BAND_RECORDING_SAVED = "BAND_RECORDING_SAVED"
RECORDING_STARTED = "RECORDING_STARTED"
RECORDING_ENDED = "RECORDING_ENDED"
RECORDING_MASTER_MIX_COMPLETE = "RECORDING_MASTER_MIX_COMPLETE"
# band notifications
BAND_INVITATION = "BAND_INVITATION"
BAND_INVITATION_ACCEPTED = "BAND_INVITATION_ACCEPTED"
BAND_SESSION_JOIN = "BAND_SESSION_JOIN" # cleared using SESSION_ENDED notification
end

View File

@ -46,8 +46,10 @@ module ValidationMessages
# recordings
ALREADY_BEING_RECORDED = "already being recorded"
ALREADY_PLAYBACK_RECORDING = "already playing a recording"
NO_LONGER_RECORDING = "no longer recording"
NOT_IN_SESSION = "not in session"
PREVIOUS_RECORDING_STILL_BEING_FINALIZED = "still has previous recording being finalized"
# recorded tracks
ALREADY_UPLOADED = "already set"
@ -59,6 +61,10 @@ module ValidationMessages
PART_NOT_STARTED = "not started"
UPLOAD_FAILURES_EXCEEDED = "exceeded"
# music sessions
MUST_BE_A_MUSICIAN = "must be a musician"
CLAIMED_RECORDING_ALREADY_IN_PROGRESS = "already started by someone else"
# takes either a string/string hash, or a string/array-of-strings|symbols hash,
# and creates a ActiveRecord.errors style object

View File

@ -1,21 +0,0 @@
require 'json'
require 'resque'
module JamRuby
@queue = :audiomixer
class AudioMixer
def self.perform(manifest)
tmp = Dir::Tmpname.make_tmpname "/var/tmp/audiomixer/manifest-#{manifest['recordingId']}", nil
File.open(tmp,"w") do |f|
f.write(manifest.to_json)
end
system("tar zxvf some_big_tarball.tar.gz"))
end
end
end

View File

@ -19,8 +19,8 @@ module JamRuby
"s3://#{@aws_bucket}/#{filename}"
end
def url(filename)
"https://s3.amazonaws.com/#{@aws_bucket}/#{filename}"
def url(filename, options = @@def_opts)
"http#{options[:secure] ? "s" : ""}://s3.amazonaws.com/#{@aws_bucket}/#{filename}"
end
def upload_sign(filename, content_md5, part_number, upload_id)

View File

@ -1,4 +1,4 @@
module JamRuby
module JamRuby
# creates messages (implementation: protocol buffer) objects cleanly
class MessageFactory
@ -9,18 +9,18 @@
CLIENT_TARGET_PREFIX = "client:"
def initialize()
@type_values = {}
@type_values = {}
Jampb::ClientMessage::Type.constants.each do |constant|
@type_values[Jampb::ClientMessage::Type.const_get(constant)] = constant
end
Jampb::ClientMessage::Type.constants.each do |constant|
@type_values[Jampb::ClientMessage::Type.const_get(constant)] = constant
end
end
# given a string (bytes) payload, return a client message
def parse_client_msg(payload)
return Jampb::ClientMessage.parse(payload)
end
# given a string (bytes) payload, return a client message
def parse_client_msg(payload)
return Jampb::ClientMessage.parse(payload)
end
# create a login message using user/pass
def login_with_user_pass(username, password, options = {})
@ -70,6 +70,16 @@
)
end
def download_available
download_available = Jampb::DownloadAvailable.new
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::DOWNLOAD_AVAILABLE,
:route_to => CLIENT_TARGET,
:download_available => download_available
)
end
# create a music session login message
def login_music_session(music_session)
login_music_session = Jampb::LoginMusicSession.new(:music_session => music_session)
@ -114,6 +124,28 @@
)
end
# create a heartbeat
def heartbeat()
heartbeat = Jampb::Heartbeat.new
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::HEARTBEAT,
:route_to => SERVER_TARGET,
:heartbeat => heartbeat
)
end
# create a heartbeat ack
def heartbeat_ack()
heartbeat_ack = Jampb::HeartbeatAck.new
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::HEARTBEAT_ACK,
:route_to => CLIENT_TARGET,
:heartbeat_ack => heartbeat_ack
)
end
# create a server bad state recovered msg
def server_bad_state_recovered(original_message_id)
recovered = Jampb::ServerBadStateRecovered.new()
@ -126,7 +158,7 @@
)
end
# create a server error
# create a server error
def server_generic_error(error_msg)
error = Jampb::ServerGenericError.new(:error_msg => error_msg)
@ -137,7 +169,7 @@
)
end
# create a server rejection error
# create a server rejection error
def server_rejection_error(error_msg)
error = Jampb::ServerRejectionError.new(:error_msg => error_msg)
@ -172,52 +204,310 @@
)
end
# create a friend joined session message
def friend_session_join(session_id, user_id, username, photo_url)
join = Jampb::FriendSessionJoin.new(
:session_id => session_id,
###################################### NOTIFICATIONS ######################################
# create a friend update message
def friend_update(user_id, photo_url, online, msg)
friend = Jampb::FriendUpdate.new(
:user_id => user_id,
:username => username,
:photo_url => photo_url
:photo_url => photo_url,
:online => online,
:msg => msg
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::FRIEND_SESSION_JOIN,
:route_to => CLIENT_TARGET,
:friend_session_join => join
:type => ClientMessage::Type::FRIEND_UPDATE,
:route_to => USER_TARGET_PREFIX + user_id,
:friend_update => friend
)
end
# create a musician joined session message
def musician_session_join(session_id, user_id, username, photo_url)
join = Jampb::MusicianSessionJoin.new(
# create a friend request message
def friend_request(receiver_id, friend_request_id, photo_url, msg, notification_id, created_at)
friend_request = Jampb::FriendRequest.new(
:friend_request_id => friend_request_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::FRIEND_REQUEST,
:route_to => USER_TARGET_PREFIX + receiver_id,
:friend_request => friend_request
)
end
# create a friend request acceptance message
def friend_request_accepted(receiver_id, photo_url, msg, notification_id, created_at)
friend_request_accepted = Jampb::FriendRequestAccepted.new(
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:friend_request_accepted => friend_request_accepted
)
end
def new_user_follower(receiver_id, photo_url, msg, notification_id, created_at)
new_user_follower = Jampb::NewUserFollower.new(
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::NEW_USER_FOLLOWER,
:route_to => USER_TARGET_PREFIX + receiver_id,
:new_user_follower => new_user_follower
)
end
def new_band_follower(receiver_id, photo_url, msg, notification_id, created_at)
new_band_follower = Jampb::NewBandFollower.new(
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::NEW_BAND_FOLLOWER,
:route_to => USER_TARGET_PREFIX + receiver_id,
:new_band_follower => new_band_follower
)
end
def session_invitation(receiver_id, session_id, msg, notification_id, created_at)
session_invitation = Jampb::SessionInvitation.new(
:session_id => session_id,
:user_id => user_id,
:username => username,
:photo_url => photo_url
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::SESSION_INVITATION,
:route_to => USER_TARGET_PREFIX + receiver_id,
:session_invitation => session_invitation
)
end
# create a join request session message
def join_request(join_request_id, session_id, photo_url, msg, notification_id, created_at)
req = Jampb::JoinRequest.new(
:join_request_id => join_request_id,
:session_id => session_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::JOIN_REQUEST,
:route_to => SESSION_TARGET_PREFIX + session_id,
:join_request => req
)
end
# create a join request approved session message
def join_request_approved(join_request_id, session_id, photo_url, msg, notification_id, created_at)
req_approved = Jampb::JoinRequestApproved.new(
:join_request_id => join_request_id,
:session_id => session_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::JOIN_REQUEST_APPROVED,
:route_to => SESSION_TARGET_PREFIX + session_id,
:join_request_approved => req_approved
)
end
# create a join request rejected session message
def join_request_rejected(join_request_id, session_id, photo_url, msg, notification_id, created_at)
req_rejected = Jampb::JoinRequestRejected.new(
:join_request_id => join_request_id,
:session_id => session_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::JOIN_REQUEST_REJECTED,
:route_to => SESSION_TARGET_PREFIX + session_id,
:join_request_rejected => req_rejected
)
end
def session_join(session_id, photo_url, msg)
join = Jampb::SessionJoin.new(
:session_id => session_id,
:photo_url => photo_url,
:msg => msg
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::SESSION_JOIN,
:route_to => CLIENT_TARGET,
:session_join => join
)
end
def session_depart(session_id, photo_url, msg, recording_id = nil)
left = Jampb::SessionDepart.new(
:session_id => session_id,
:photo_url => photo_url,
:msg => msg,
:recording_id => recording_id
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::SESSION_DEPART,
:route_to => CLIENT_TARGET,
:session_depart => left
)
end
def musician_session_join(receiver_id, session_id, photo_url, msg, notification_id, created_at)
musician_session_join = Jampb::MusicianSessionJoin.new(
:session_id => session_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::MUSICIAN_SESSION_JOIN,
:route_to => CLIENT_TARGET,
:musician_session_join => join
:route_to => USER_TARGET_PREFIX + receiver_id,
:musician_session_join => musician_session_join
)
end
# create a musician left session message
def musician_session_depart(session_id, user_id, username, photo_url, recordingId = nil)
left = Jampb::MusicianSessionDepart.new(
:session_id => session_id,
:user_id => user_id,
:username => username,
def band_session_join(receiver_id, session_id, photo_url, msg, notification_id, created_at)
band_session_join = Jampb::BandSessionJoin.new(
:session_id => session_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::BAND_SESSION_JOIN,
:route_to => USER_TARGET_PREFIX + receiver_id,
:band_session_join => band_session_join
)
end
def musician_recording_saved(receiver_id, recording_id, photo_url, msg, notification_id, created_at)
musician_recording_saved = Jampb::MusicianRecordingSaved.new(
:recording_id => recording_id,
:photo_url => photo_url,
:recordingId => recordingId
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::MUSICIAN_SESSION_DEPART,
:route_to => CLIENT_TARGET,
:musician_session_depart => left
:type => ClientMessage::Type::MUSICIAN_RECORDING_SAVED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:musician_recording_saved => musician_recording_saved
)
end
def band_recording_saved(receiver_id, recording_id, photo_url, msg, notification_id, created_at)
band_recording_saved = Jampb::BandRecordingSaved.new(
:recording_id => recording_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::BAND_RECORDING_SAVED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:band_recording_saved => band_recording_saved
)
end
def recording_started(receiver_id, photo_url, msg)
recording_started = Jampb::RecordingStarted.new(
:photo_url => photo_url,
:msg => msg
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::RECORDING_STARTED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:recording_started => recording_started
)
end
def recording_ended(receiver_id, photo_url, msg)
recording_ended = Jampb::RecordingEnded.new(
:photo_url => photo_url,
:msg => msg
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::RECORDING_ENDED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:recording_ended => recording_ended
)
end
def recording_master_mix_complete
end
# create a band invitation message
def band_invitation(receiver_id, invitation_id, band_id, photo_url, msg, notification_id, created_at)
band_invitation = Jampb::BandInvitation.new(
:band_invitation_id => invitation_id,
:band_id => band_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::BAND_INVITATION,
:route_to => USER_TARGET_PREFIX + receiver_id,
:band_invitation => band_invitation
)
end
# create a band invitation acceptance message
def band_invitation_accepted(receiver_id, invitation_id, photo_url, msg, notification_id, created_at)
band_invitation_accepted = Jampb::BandInvitationAccepted.new(
:band_invitation_id => invitation_id,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::BAND_INVITATION_ACCEPTED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:band_invitation_accepted => band_invitation_accepted
)
end
@ -253,183 +543,14 @@
)
end
# create a join request session message
def join_request(join_request_id, session_id, username, photo_url, msg, notification_id, created_at)
req = Jampb::JoinRequest.new(
:join_request_id => join_request_id,
:session_id => session_id,
:username => username,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::JOIN_REQUEST,
:route_to => SESSION_TARGET_PREFIX + session_id,
:join_request => req
)
end
# create a join request approved session message
def join_request_approved(join_request_id, session_id, username, photo_url, msg, notification_id, created_at)
req_approved = Jampb::JoinRequestApproved.new(
:join_request_id => join_request_id,
:session_id => session_id,
:username => username,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::JOIN_REQUEST_APPROVED,
:route_to => SESSION_TARGET_PREFIX + session_id,
:join_request_approved => req_approved
)
end
# create a join request rejected session message
def join_request_rejected(join_request_id, session_id, username, photo_url, msg, notification_id, created_at)
req_rejected = Jampb::JoinRequestRejected.new(
:join_request_id => join_request_id,
:session_id => session_id,
:username => username,
:photo_url => photo_url,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::JOIN_REQUEST_REJECTED,
:route_to => SESSION_TARGET_PREFIX + session_id,
:join_request_rejected => req_rejected
)
end
# create a band invitation message
def band_invitation(invitation_id, band_id, receiver_id, username, photo_url, band_name, msg, notification_id, created_at)
band_invitation = Jampb::BandInvitation.new(
:band_invitation_id => invitation_id,
:band_id => band_id,
:user_id => receiver_id,
:username => username,
:photo_url => photo_url,
:band_name => band_name,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::BAND_INVITATION,
:route_to => USER_TARGET_PREFIX + receiver_id,
:band_invitation => band_invitation
)
end
# create a band invitation acceptance message
def band_invitation_accepted(invitation_id, receiver_id, username, photo_url, band_name, msg, notification_id, created_at)
band_invitation_accepted = Jampb::BandInvitationAccepted.new(
:band_invitation_id => invitation_id,
:user_id => receiver_id,
:username => username,
:photo_url => photo_url,
:band_name => band_name,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::BAND_INVITATION_ACCEPTED,
:route_to => USER_TARGET_PREFIX + receiver_id,
:band_invitation_accepted => band_invitation_accepted
)
end
# create a test message to send in session
def test_session_message(session_id, msg)
test = Jampb::TestSessionMessage.new(:msg => msg)
# create a test message to send in session
def test_session_message(session_id, msg)
test = Jampb::TestSessionMessage.new(:msg => msg)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::TEST_SESSION_MESSAGE,
:route_to => SESSION_TARGET_PREFIX + session_id,
:test_session_message => test
)
end
def session_invitation(receiver_id, sender_name, session_id, notification_id, created_at)
session_invitation = Jampb::SessionInvitation.new(
:sender_name => sender_name,
:session_id => session_id,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::SESSION_INVITATION,
:route_to => USER_TARGET_PREFIX + receiver_id,
:session_invitation => session_invitation
)
end
# create a friend update message
def friend_update(user_id, name, photo_url, online, msg)
friend = Jampb::FriendUpdate.new(
:user_id => user_id,
:name => name,
:photo_url => photo_url,
:online => online,
:msg => msg
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::FRIEND_UPDATE,
:route_to => USER_TARGET_PREFIX + user_id,
:friend_update => friend
)
end
# create a friend request message
def friend_request(friend_request_id, user_id, name, photo_url, friend_id, msg, notification_id, created_at)
friend_request = Jampb::FriendRequest.new(
:friend_request_id => friend_request_id,
:user_id => user_id,
:name => name,
:photo_url => photo_url,
:friend_id => friend_id,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::FRIEND_REQUEST,
:route_to => USER_TARGET_PREFIX + friend_id,
:friend_request => friend_request
)
end
# create a friend request acceptance message
def friend_request_accepted(friend_id, name, photo_url, user_id, msg, notification_id, created_at)
friend_request_accepted = Jampb::FriendRequestAccepted.new(
:friend_id => friend_id,
:name => name,
:photo_url => photo_url,
:user_id => user_id,
:msg => msg,
:notification_id => notification_id,
:created_at => created_at
)
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED,
:route_to => USER_TARGET_PREFIX + user_id,
:friend_request_accepted => friend_request_accepted
)
end
@ -473,28 +594,6 @@
####################################################
# create a heartbeat
def heartbeat()
heartbeat = Jampb::Heartbeat.new
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::HEARTBEAT,
:route_to => SERVER_TARGET,
:heartbeat => heartbeat
)
end
# create a heartbeat ack
def heartbeat_ack()
heartbeat_ack = Jampb::HeartbeatAck.new
return Jampb::ClientMessage.new(
:type => ClientMessage::Type::HEARTBEAT_ACK,
:route_to => CLIENT_TARGET,
:heartbeat_ack => heartbeat_ack
)
end
# is this message directed to the server?
def server_directed? msg
return msg.route_to == MessageFactory::SERVER_TARGET
@ -519,8 +618,8 @@
return msg.route_to[MessageFactory::SESSION_TARGET_PREFIX..-1]
end
def get_message_type msg
return @type_values[msg.type]
end
def get_message_type msg
return @type_values[msg.type]
end
end
end

View File

@ -1,13 +1,19 @@
module JamRuby
class ClaimedRecording < ActiveRecord::Base
validates :name, no_profanity: true
validates :description, no_profanity: true
validates :name, no_profanity: true, length: {minimum: 3, maximum: 64}, presence: true
validates :description, no_profanity: true, length: {maximum: 8000}
validates :is_public, :inclusion => {:in => [true, false]}
validates :is_downloadable, :inclusion => {:in => [true, false]}
validates :genre, presence: true
validates_uniqueness_of :recording_id, :scope => :user_id
belongs_to :recording, :class_name => "JamRuby::Recording", :inverse_of => :claimed_recordings
belongs_to :user, :class_name => "JamRuby::User", :inverse_of => :claimed_recordings
belongs_to :genre, :class_name => "JamRuby::Genre"
has_many :recorded_tracks, :through => :recording, :class_name => "JamRuby::RecordedTrack"
has_many :playing_sessions, :class_name => "JamRuby::MusicSession"
# user must own this object
# params is a hash, and everything is optional
@ -31,7 +37,7 @@ module JamRuby
# If this is the only copy, destroy the entire recording. Otherwise, just destroy this claimed_recording
if recording.claimed_recordings.count == 1
recording.discard
recording.destroy
else
self.destroy
end

View File

@ -0,0 +1,9 @@
module JamRuby
class IcecastAdminAuthentication < ActiveRecord::Base
self.primary_key = 'id'
validates :source_password, length: {minimum: 5}
end
end

View File

@ -0,0 +1,9 @@
module JamRuby
class IcecastDirectory < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,13 @@
module JamRuby
class IcecastLimit < ActiveRecord::Base
self.primary_key = 'id'
validates :clients, numericality: {only_integer: true}
def dumpXml()
end
end
end

View File

@ -0,0 +1,8 @@
module JamRuby
class IcecastListenSocket < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,9 @@
module JamRuby
class IcecastLogging < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,7 @@
module JamRuby
class IcecastMastersvrRelay < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,9 @@
module JamRuby
class IcecastMount < ActiveRecord::Base
self.primary_key = 'id'
has_one :authentication, :class_name => "IcecastUserAuthentication"
end
end

View File

@ -0,0 +1,9 @@
module JamRuby
class IcecastPath < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,8 @@
module JamRuby
class IcecastRelay < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,9 @@
module JamRuby
class IcecastSecurity < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,18 @@
module JamRuby
class IcecastServer < ActiveRecord::Base
self.primary_key = 'id'
has_one :limit, :class_name => "JamRuby::IcecastLimit"
has_one :adminauth, :class_name => "JamRuby::IcecastAdminAuthentication"
has_one :directory, :class_name => "JamRuby::IcecastDirectory"
has_one :misc, :class_name => "JamRuby::IcecastServermisc"
has_many :listen_sockets, :class_name => "JamRuby::IcecastListenSocket"
has_one :master_relay, :class_name => "JamRuby::IcecastMastersvrRelay"
has_one :relay, :class_name => "JamRuby::IcecastRelay"
has_many :mounts, :class_name => "JamRuby::IcecastMount"
has_one :path, :class_name => "JamRuby::IcecastPath"
has_one :logging, :class_name => "JamRuby::IcecastLogging"
has_one :security, :class_name => "JamRuby::IceCastSecurity"
end
end

View File

@ -0,0 +1,7 @@
module JamRuby
class IcecastServermisc < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -0,0 +1,8 @@
module JamRuby
class IcecastUserAuthentication < ActiveRecord::Base
self.primary_key = 'id'
end
end

View File

@ -6,6 +6,8 @@ module JamRuby
attr_accessible :creator, :description, :musician_access, :approval_required, :fan_chat, :fan_access, :genres
belongs_to :creator, :inverse_of => :music_sessions, :class_name => "JamRuby::User", :foreign_key => "user_id"
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_many :connections, :class_name => "JamRuby::Connection"
has_many :users, :through => :connections, :class_name => "JamRuby::User"
@ -33,10 +35,20 @@ module JamRuby
validates :legal_terms, :inclusion => {:in => [true]}, :on => :create
validates :creator, :presence => true
validate :creator_is_musician
validate :no_new_playback_while_playing
def creator_is_musician
unless creator.musician?
errors.add(:creator, "must be a 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
@ -167,11 +179,19 @@ module JamRuby
return self.users.exists? 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
@ -182,8 +202,20 @@ module JamRuby
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 to_s
return description
description
end
private

View File

@ -12,8 +12,7 @@ module JamRuby
belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id"
def index(user_id)
results = Notification.where(:target_user_id => user_id).limit(50)
return results
Notification.where(:target_user_id => user_id).limit(50)
end
def photo_url
@ -25,37 +24,17 @@ module JamRuby
# used for persisted notifications
def formatted_msg
# target_user, band, session, recording, invitation, join_request = nil
source_user = nil
# unless self.target_user_id.nil?
# target_user = User.find(self.target_user_id)
# end
source_user, band = nil
unless self.source_user_id.nil?
source_user = User.find(self.source_user_id)
end
# unless self.band_id.nil?
# band = Band.find(self.band_id)
# end
unless self.band_id.nil?
band = Band.find(self.band_id)
end
# unless self.session_id.nil?
# session = MusicSession.find(self.session_id)
# end
# unless self.recording_id.nil?
# recording = Recording.find(self.recording_id)
# end
# unless self.invitation_id.nil?
# invitation = Invitation.find(self.invitation_id)
# end
# unless self.join_request_id.nil?
# join_request = JoinRequest.find(self.join_request_id)
# end
return self.class.format_msg(self.description, source_user)
return self.class.format_msg(self.description, source_user, band)
end
# TODO: MAKE ALL METHODS BELOW ASYNC SO THE CLIENT DOESN'T BLOCK ON NOTIFICATION LOGIC
@ -81,7 +60,7 @@ module JamRuby
return friend_ids
end
def retrieve_followers(connection, user_id)
def retrieve_user_followers(connection, user_id)
follower_ids = []
connection.exec("SELECT uf.follower_id as friend_id FROM users_followers uf WHERE uf.user_id = $1", [user_id]) do |follower_results|
follower_results.each do |follower_result|
@ -91,9 +70,20 @@ module JamRuby
return follower_ids
end
def retrieve_friends_not_in_session(connection, user_id, session_id)
ids = retrieve_friends(connection, user_id)
connection.exec("SELECT c.user_id as musician_id FROM connections c WHERE c.music_session_id = $1", [session_id]) do |musicians|
musicians.each do |musician_result|
# remove users who are in the session
ids.reject! {|item| item == musician_result['musician_id']}
end
end
return ids
end
def retrieve_friends_and_followers(connection, user_id)
ids = retrieve_friends(connection, user_id)
ids.concat(retrieve_followers(connection, user_id))
ids.concat(retrieve_user_followers(connection, user_id))
ids.uniq! {|id| id}
return ids
end
@ -109,15 +99,21 @@ module JamRuby
return ids
end
def format_msg(description, user = nil)
name = ""
def format_msg(description, user = nil, band = nil)
name, band_name = ""
unless user.nil?
name = user.name
else
name = "Someone"
end
if !band.nil?
band_name = band.name
end
case description
# friend notifications
when NotificationTypes::FRIEND_UPDATE
return "#{name} is now "
@ -127,15 +123,13 @@ module JamRuby
when NotificationTypes::FRIEND_REQUEST_ACCEPTED
return "#{name} has accepted your friend request."
when NotificationTypes::FRIEND_SESSION_JOIN
return "#{name} has joined the session."
when NotificationTypes::NEW_USER_FOLLOWER
return "#{name} is now following you on JamKazam."
when NotificationTypes::MUSICIAN_SESSION_JOIN
return "#{name} has joined the session."
when NotificationTypes::MUSICIAN_SESSION_DEPART
return "#{name} has left the session."
when NotificationTypes::NEW_BAND_FOLLOWER
return "#{name} is now following your band #{band.name} on JamKazam."
# session notifications
when NotificationTypes::SESSION_INVITATION
return "#{name} has invited you to a session."
@ -148,46 +142,72 @@ module JamRuby
when NotificationTypes::JOIN_REQUEST_REJECTED
return "We're sorry, but you cannot join the session at this time."
when NotificationTypes::SESSION_JOIN
return "#{name} has joined the session."
when NotificationTypes::SESSION_DEPART
return "#{name} has left the session."
when NotificationTypes::MUSICIAN_SESSION_JOIN
return "#{name} is now in a session."
when NotificationTypes::BAND_SESSION_JOIN
return "#{band_name} is now in a session."
# recording notifications
when NotificationTypes::MUSICIAN_RECORDING_SAVED
return "#{name} has made a new recording."
when NotificationTypes::BAND_RECORDING_SAVED
return "#{band.name} has made a new recording."
when NotificationTypes::RECORDING_STARTED
return "#{name} has started a recording."
when NotificationTypes::RECORDING_ENDED
return "#{name} has stopped recording."
when NotificationTypes::RECORDING_MASTER_MIX_COMPLETE
return "This recording has been mastered and mixed and is ready to share."
# band notifications
when NotificationTypes::BAND_INVITATION
return "You have been invited to join the band #{name}."
return "You have been invited to join the band #{band_name}."
when NotificationTypes::BAND_INVITATION_ACCEPTED
return "#{name} has accepted your band invitation."
return "#{name} has accepted your band invitation to join #{band_name}."
else
return ""
end
end
################### FRIEND UPDATE ###################
def send_friend_update(user_id, online, connection)
# (1) get all of this user's friends
friend_ids = retrieve_friends(connection, user_id)
unless friend_ids.blank?
unless friend_ids.empty?
user = User.find(user_id)
# (2) create notification
online_msg = online ? "online." : "offline."
notification_msg = format_msg(NotificationTypes::FRIEND_UPDATE, user) + online_msg
msg = @@message_factory.friend_update(
user_id, user.name,
user.id,
user.photo_url,
online,
notification_msg
)
# (3) send notification
@@mq_router.publish_to_friends(friend_ids, msg, user_id)
end
end
################### FRIEND REQUEST ###################
def send_friend_request(friend_request_id, user_id, friend_id)
user = User.find(user_id)
friend = User.find(friend_id)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::FRIEND_REQUEST
notification.source_user_id = user_id
@ -195,157 +215,151 @@ module JamRuby
notification.friend_request_id = friend_request_id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, user)
msg = @@message_factory.friend_request(
friend_request_id,
user_id,
user.name,
user.photo_url,
friend_id,
notification_msg,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_user(friend_id, msg)
if friend.online
msg = @@message_factory.friend_request(
friend.id,
friend_request_id,
user.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(friend_id, msg)
else
UserMailer.friend_request(friend.email, notification_msg)
end
end
############### FRIEND REQUEST ACCEPTED ###############
def send_friend_request_accepted(user_id, friend_id)
friend = User.find(friend_id)
user = User.find(user_id)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::FRIEND_REQUEST_ACCEPTED
notification.source_user_id = friend_id
notification.target_user_id = user_id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, friend)
msg = @@message_factory.friend_request_accepted(
friend_id,
friend.name,
friend.photo_url,
user_id, notification_msg,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_user(user_id, msg)
end
################## SESSION INVITATION ##################
def send_session_invitation(receiver_id, sender, session_id)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::SESSION_INVITATION
notification.source_user_id = sender.id
notification.target_user_id = receiver_id
notification.session_id = session_id
notification.save
# (2) create notification
msg = @@message_factory.session_invitation(
receiver_id,
sender.name,
session_id,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_user(receiver_id, msg)
end
################## SESSION INVITATION ##################
def send_musician_session_join(music_session, connection, user)
# (1) create notification
msg = @@message_factory.musician_session_join(
music_session.id,
user.id,
user.name,
user.photo_url
)
# (2) send notification
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => connection.client_id})
end
################## MUSICIAN SESSION DEPART ##################
def send_musician_session_depart(music_session, client_id, user, recordingId = nil)
# (1) create notification
msg = @@message_factory.musician_session_depart(
music_session.id,
user.id,
user.name,
user.photo_url,
recordingId
)
# (2) send notification
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
end
################## MUSICIAN SESSION FRESH ##################
def send_musician_session_fresh(music_session, client_id, user)
# (1) create notification
msg = @@message_factory.musician_session_fresh(
music_session.id,
user.id,
user.name,
user.photo_url
)
# (2) send notification
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
end
################## MUSICIAN SESSION STALE ##################
def send_musician_session_stale(music_session, client_id, user)
# (1) create notification
msg = @@message_factory.musician_session_stale(
music_session.id,
user.id,
user.name,
user.photo_url
)
# (2) send notification
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
end
################## FRIEND SESSION JOIN ##################
def send_friend_session_join(db_conn, connection, user)
ids = retrieve_friends_and_followers_not_in_session(db_conn, user.id, connection.music_session.id)
if ids.length > 0
# (1) save to database
# (2) create notification
msg = @@message_factory.friend_session_join(
connection.music_session.id,
if user.online
msg = @@message_factory.friend_request_accepted(
user.id,
user.name,
user.photo_url)
friend.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_friends(ids, msg, sender = {:client_id => connection.client_id})
@@mq_router.publish_to_user(user.id, msg)
else
UserMailer.friend_request_accepted(user.email, notification_msg)
end
end
################## JOIN REQUEST ##################
def send_new_user_follower(follower, user)
notification = Notification.new
notification.description = NotificationTypes::NEW_USER_FOLLOWER
notification.source_user_id = follower.id
notification.target_user_id = user.id
notification.save
notification_msg = format_msg(notification.description, follower)
if follower.id != user.id
if user.online
msg = @@message_factory.new_user_follower(
user.id,
follower.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(user.id, msg)
else
UserMailer.new_user_follower(user.email, notification_msg)
end
end
end
def send_new_band_follower(follower, band)
notifications = []
band.band_musicians.each.each do |bm|
notification = Notification.new
notification.description = NotificationTypes::NEW_BAND_FOLLOWER
notification.source_user_id = follower.id
notification.target_user_id = bm.user_id
notification.band_id = band.id
notification.save
notification_msg = format_msg(notification.description, follower, band)
# this protects against sending the notification to a band member who decides to follow the band
if follower.id != bm.user.id
if bm.user.online
msg = @@message_factory.new_user_follower(
bm.user_id,
follower.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(bm.user_id, msg)
else
UserMailer.new_band_follower(bm.user.email, notification_msg)
end
end
end
end
def send_session_invitation(receiver, sender, session_id)
notification = Notification.new
notification.description = NotificationTypes::SESSION_INVITATION
notification.source_user_id = sender.id
notification.target_user_id = receiver.id
notification.session_id = session_id
notification.save
notification_msg = format_msg(NotificationTypes::SESSION_INVITATION, sender)
if receiver.online
msg = @@message_factory.session_invitation(
receiver.id,
session_id,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(receiver.id, msg)
else
UserMailer.session_invitation(receiver.email, notification_msg)
end
end
def send_session_ended(music_session, connection)
# TODO: this should actually publish to all users who have a notification for this session
@@mq_router.server_publish_to_session(music_session, nil, sender = {:client_id => connection.client_id})
end
def send_join_request(music_session, join_request, text)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::JOIN_REQUEST
notification.source_user_id = join_request.user.id
@ -353,26 +367,22 @@ module JamRuby
notification.session_id = music_session.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, join_request.user)
msg = @@message_factory.join_request(
join_request.id,
music_session.id,
join_request.user.name,
join_request.user.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_user(music_session.creator.id, msg)
end
################## JOIN REQUEST APPROVED ##################
def send_join_request_approved(music_session, join_request)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::JOIN_REQUEST_APPROVED
notification.source_user_id = music_session.creator.id
@ -380,26 +390,22 @@ module JamRuby
notification.session_id = music_session.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, music_session.creator)
msg = @@message_factory.join_request_approved(
join_request.id,
music_session.id,
music_session.creator.name,
music_session.creator.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_user(join_request.user.id, msg)
end
################## JOIN REQUEST REJECTED ##################
def send_join_request_rejected(music_session, join_request)
# (1) save to database
notification = Notification.new
notification.description = NotificationTypes::JOIN_REQUEST_REJECTED
notification.source_user_id = music_session.creator.id
@ -407,26 +413,255 @@ module JamRuby
notification.session_id = music_session.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, music_session.creator)
msg = @@message_factory.join_request_rejected(
join_request.id,
music_session.id,
music_session.creator.name,
music_session.creator.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
# (3) send notification
@@mq_router.publish_to_user(join_request.user.id, msg)
end
################## BAND INVITATION ##################
def send_session_join(music_session, connection, user)
notification_msg = format_msg(NotificationTypes::SESSION_JOIN, user)
msg = @@message_factory.session_join(
music_session.id,
user.photo_url,
notification_msg
)
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => connection.client_id})
end
def send_session_depart(music_session, client_id, user, recordingId = nil)
notification_msg = format_msg(NotificationTypes::SESSION_DEPART, user)
msg = @@message_factory.session_depart(
music_session.id,
user.photo_url,
notification_msg,
recordingId
)
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
end
def send_musician_session_join(music_session, connection, user)
if music_session.musician_access || music_session.fan_access
friends = Friendship.where(:friend_id => user.id)
user_followers = UserFollower.where(:user_id => user.id)
# construct an array of User objects representing friends and followers
friend_users = friends.map { |fu| fu.user }
follower_users = user_followers.map { |uf| uf.follower }
friends_and_followers = friend_users.concat(follower_users).uniq
# remove anyone in the session
friends_and_followers = friends_and_followers - music_session.users
notifications, online_ff, offline_ff = [], [], []
notification_msg = format_msg(NotificationTypes::MUSICIAN_SESSION_JOIN, user)
friends_and_followers.each do |ff|
if (ff.musician && music_session.musician_access) || (!ff.musician && music_session.fan_access)
notification = Notification.new
notification.description = NotificationTypes::MUSICIAN_SESSION_JOIN
notification.source_user_id = user.id
notification.target_user_id = ff.id
notification.save
if ff.online
msg = @@message_factory.musician_session_join(
ff.id,
music_session.id,
user.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(ff.id, msg)
else
offline_ff << ff
end
end
end
# send email notifications
unless offline_ff.empty?
UserMailer.musician_session_join(offline_ff.map! {|f| f.email}, notification_msg)
end
end
end
def send_band_session_join(music_session, band)
# if the session is private, don't send any notifications
if music_session.musician_access || music_session.fan_access
band_followers = BandFollower.where(:band_id => band.id)
notifications, online_followers, offline_followers = [], [], []
notification_msg = format_msg(NotificationTypes::BAND_SESSION_JOIN, nil, band)
band_followers.each do |bf|
if (bf.follower.musician && music_session.musician_access) || (!bf.follower.musician && music_session.fan_access)
notification = Notification.new
notification.band_id = band.id
notification.description = NotificationTypes::BAND_SESSION_JOIN
notification.target_user_id = bf.follower.id
notification.save
if bf.follower.online
msg = @@message_factory.band_session_join(
bf.follower.id,
music_session.id,
band.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(bf.follower.id, msg)
else
offline_followers << bf.follower
end
end
end
# send email notifications
unless offline_followers.empty?
UserMailer.band_session_join(offline_followers.map! {|f| f.email}, notification_msg)
end
end
end
def send_musician_recording_saved(recording)
user = recording.owner
friends = Friendship.where(:friend_id => user.id)
user_followers = UserFollower.where(:user_id => user.id)
# construct an array of User objects representing friends and followers
friend_users = friends.map { |fu| fu.friend }
follower_users = user_followers.map { |uf| uf.follower }
friends_and_followers = friend_users.concat(follower_users).uniq
notifications, online_ff, offline_ff = [], [], []
notification_msg = format_msg(NotificationTypes::MUSICIAN_RECORDING_SAVED, user)
friends_and_followers.each do |ff|
notification = Notification.new
notification.description = NotificationTypes::MUSICIAN_SESSION_JOIN
notification.source_user_id = user.id
notification.target_user_id = ff.id
notification.save
if ff.online
msg = @@message_factory.musician_recording_saved(
ff.id,
recording.id,
user.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(ff.id, notification_msg)
else
offline_ff << ff
end
end
# send email notifications
unless offline_ff.empty?
UserMailer.musician_recording_saved(offline_ff.map! {|f| f.email}, notification_msg)
end
end
def send_band_recording_saved(recording)
band_followers = BandFollower.where(:band_id => band.id)
notification_msg = format_msg(NotificationTypes::BAND_RECORDING_SAVED, nil, recording.band)
band_followers.each do |bf|
notification = Notification.new
notification.description = NotificationTypes::BAND_RECORDING_SAVED
notification.band_id = band.id
notification.target_user_id = bf.follower.id
notification.recording_id = recording.id
notification.save
if bf.follower.online
msg = @@message_factory.band_recording_saved(
bf.follower.id,
recording.id,
band.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(of.id, notification_msg)
else
offline_followers << bf.follower
end
end
# send email notifications
unless offline_followers.empty?
UserMailer.band_recording_saved(offline_followers.map! {|f| f.email}, notification_msg)
end
end
def send_recording_started(music_session, connection, user)
notification_msg = format_msg(NotificationTypes::RECORDING_STARTED, user)
music_session.users.each do |musician|
if musician.id != user.id
msg = @@message_factory.recording_started(
musician.id,
user.photo_url,
notification_msg
)
@@mq_router.publish_to_user(musician.id, msg)
end
end
end
def send_recording_ended(music_session, connection, user)
notification_msg = format_msg(NotificationTypes::RECORDING_ENDED, user)
music_session.users.each do |musician|
if musician.id != user.id
msg = @@message_factory.recording_ended(
musician.id,
user.photo_url,
notification_msg
)
@@mq_router.publish_to_user(musician.id, msg)
end
end
end
def send_recording_master_mix_complete(recording)
end
def send_band_invitation(band, band_invitation, sender, receiver)
# (1) save to database
notification = Notification.new
notification.band_id = band.id
notification.band_invitation_id = band_invitation.id
@ -435,28 +670,28 @@ module JamRuby
notification.target_user_id = receiver.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, band)
msg = @@message_factory.band_invitation(
band_invitation.id,
band.id,
receiver.id,
sender.name,
sender.photo_url,
band.name,
notification_msg,
notification.id,
notification.created_at.to_s
)
notification_msg = format_msg(notification.description, nil, band)
# (3) send notification
@@mq_router.publish_to_user(receiver.id, msg)
if receiver.online
msg = @@message_factory.band_invitation(
receiver.id,
band_invitation.id,
band.id,
sender.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(receiver.id, msg)
else
UserMailer.band_invitation(receiver.email, notification_msg)
end
end
################## BAND INVITATION ACCEPTED ##################
def send_band_invitation_accepted(band, band_invitation, sender, receiver)
# (1) save to database
notification = Notification.new
notification.band_id = band.id
notification.description = NotificationTypes::BAND_INVITATION_ACCEPTED
@ -464,23 +699,54 @@ module JamRuby
notification.target_user_id = receiver.id
notification.save
# (2) create notification
notification_msg = format_msg(notification.description, sender)
msg = @@message_factory.band_invitation_accepted(
band_invitation.id,
receiver.id,
sender.name,
sender.photo_url,
band.name,
notification_msg,
notification.id,
notification.created_at.to_s
)
notification_msg = format_msg(notification.description, sender, band)
# (3) send notification
@@mq_router.publish_to_user(receiver.id, msg)
if receiver.online
msg = @@message_factory.band_invitation_accepted(
receiver.id,
band_invitation.id,
sender.photo_url,
notification_msg,
notification.id,
notification.created_at.to_s
)
@@mq_router.publish_to_user(receiver.id, msg)
else
UserMailer.band_invitation_accepted(receiver.email, notification_msg)
end
end
def send_musician_session_fresh(music_session, client_id, user)
msg = @@message_factory.musician_session_fresh(
music_session.id,
user.id,
user.name,
user.photo_url
)
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
end
def send_musician_session_stale(music_session, client_id, user)
msg = @@message_factory.musician_session_stale(
music_session.id,
user.id,
user.name,
user.photo_url
)
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
end
def send_download_available(user_id)
msg = @@message_factory.download_available
@@mq_router.publish_to_user(user_id, msg)
end
end
end
end

View File

@ -8,6 +8,8 @@ module JamRuby
self.table_name = "recorded_tracks"
self.primary_key = 'id'
attr_accessible :discard
SOUND = %w(mono stereo)
MAX_PART_FAILURES = 3
MAX_UPLOAD_FAILURES = 10
@ -28,6 +30,10 @@ module JamRuby
validate :validate_too_many_upload_failures
def can_download?(some_user)
!ClaimedRecording.find_by_user_id_and_recording_id(some_user.id, recording.id).nil?
end
def upload_starting?
next_part_to_upload_was == 0 && next_part_to_upload == 1
end
@ -80,7 +86,7 @@ module JamRuby
recorded_track.next_part_to_upload = 0
recorded_track.file_offset = 0
recorded_track.save
recorded_track.url = construct_filename(recording.id, track.id)
recorded_track.url = construct_filename(recording.id, track.client_track_id)
recorded_track.save
recorded_track
end
@ -154,12 +160,12 @@ module JamRuby
def filename
# construct a path for s3
RecordedTrack.construct_filename(self.recording.id, self.track_id)
RecordedTrack.construct_filename(self.recording.id, self.client_track_id)
end
def self.construct_filename(recording_id, track_id)
raise "unknown ID" unless track_id
"recordings/#{recording_id}/track-#{track_id}.ogg"
def self.construct_filename(recording_id, client_track_id)
raise "unknown ID" unless client_track_id
"recordings/#{recording_id}/track-#{client_track_id}.ogg"
end
end
end

View File

@ -5,6 +5,8 @@ module JamRuby
observe JamRuby::RecordedTrack
def before_validation(recorded_track)
# if we see that a part was just uploaded entirely, validate that we can find the part that was just uploaded
if recorded_track.is_part_uploading_was && !recorded_track.is_part_uploading
begin
aws_part = recorded_track.s3_manager.multiple_upload_find_part(recorded_track.url, recorded_track.upload_id, recorded_track.next_part_to_upload - 1)
@ -22,10 +24,13 @@ module JamRuby
end
# if we detect that this just became fully uploaded
# if we detect that this just became fully uploaded -- if so, tell s3 to put the parts together
if !recorded_track.fully_uploaded_was && recorded_track.fully_uploaded
multipart_success = false
begin
recorded_track.s3_manager.multipart_upload_complete(recorded_track.url, recorded_track.upload_id)
multipart_success = true
rescue SocketError => e
raise # this should cause a 500 error, which is what we want. The client will retry later.
rescue Exception => e
@ -34,6 +39,11 @@ module JamRuby
recorded_track.errors.add(:upload_id, ValidationMessages::BAD_UPLOAD)
end
# tell all users that a download is available, except for the user who just uploaded
recorded_track.recording.users.each do |user|
Notification.send_download_available(recorded_track.user_id) unless user == recorded_track.user
end
end
end
@ -41,6 +51,7 @@ module JamRuby
end
# here we tick upload failure counts, or revert the state of the model, as needed
def after_rollback(recorded_track)
# if fully uploaded, don't increment failures
if recorded_track.fully_uploaded

View File

@ -14,6 +14,8 @@ module JamRuby
has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :foreign_key => :recording_id
validates :music_session, :presence => true
validate :not_already_recording, :on => :create
validate :not_still_finalizing_previous, :on => :create
validate :not_playback_recording, :on => :create
validate :already_stopped_recording
def not_already_recording
@ -22,12 +24,51 @@ module JamRuby
end
end
def not_still_finalizing_previous
# after a recording is done, users need to keep or discard it.
# this checks if the previous recording is still being finalized
unless music_session.is_recording?
previous_recording = music_session.most_recent_recording
if previous_recording
previous_recording.recorded_tracks.each do |recorded_track|
# if at least one user hasn't taken any action yet...
if recorded_track.discard.nil?
# and they are still around and in this music session still...
connection = Connection.find_by_client_id(recorded_track.client_id)
if !connection.nil? && connection.music_session == music_session
errors.add(:music_session, ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED)
break
end
end
end
end
end
end
def not_playback_recording
if music_session.is_playing_recording?
errors.add(:music_session, ValidationMessages::ALREADY_PLAYBACK_RECORDING)
end
end
def already_stopped_recording
if is_done && is_done_was
errors.add(:music_session, ValidationMessages::NO_LONGER_RECORDING)
end
end
def recorded_tracks_for_user(user)
unless self.users.exists?(user)
raise PermissionError, "user was not in this session"
end
recorded_tracks.where(:user_id=> user.id)
end
def has_access?(user)
return users.exists?(user)
end
# Start recording a session.
def self.start(music_session, owner)
recording = nil
@ -46,16 +87,9 @@ module JamRuby
end
end
end
# 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
connection = Connection.where(:user_id => owner.id).where(:music_session_id => music_session.id).first
Notification.send_recording_started(music_session, connection, owner)
recording
end
@ -70,27 +104,21 @@ module JamRuby
self.is_done = true
self.save
end
connection = Connection.where(:user_id => self.owner.id).where(:music_session_id => music_session.id).first
Notification.send_recording_ended(music_session, connection, self.owner)
self
end
# Called when a user wants to "claim" a recording. To do this, the user must have been one of the tracks in the recording.
def claim(user, name, description, genre, is_public, is_downloadable)
# if self.users.include?(user)
# raise PermissionError, "user already claimed this recording"
# end
unless self.users.exists?(user)
raise PermissionError, "user was not in this session"
end
if self.music_session.is_recording?
raise PermissionError, "recording cannot be claimed while it is being recorded"
end
if name.nil? || genre.nil? || is_public.nil? || is_downloadable.nil?
raise PermissionError, "recording must have name, genre and flags"
end
claimed_recording = ClaimedRecording.new
claimed_recording.user = user
claimed_recording.recording = self
@ -101,8 +129,23 @@ module JamRuby
claimed_recording.is_downloadable = is_downloadable
self.claimed_recordings << claimed_recording
if claimed_recording.save
keep(user)
end
claimed_recording
end
# the user votes to keep their tracks for this recording
def keep(user)
recorded_tracks_for_user(user).update_all(:discard => false)
end
# the user votes to discard their tracks for this recording
def discard(user)
recorded_tracks_for_user(user).update_all(:discard => true)
end
# Find out if all the tracks for this recording have been uploaded
def uploaded?
@ -112,85 +155,53 @@ module JamRuby
return true
end
# Discards this recording and schedules deletion of all files associated with it.
def discard
self.destroy
end
# Returns the list of files the user needs to upload. This will only ever be recordings
def self.upload_file_list(user)
files = []
User.joins(:recordings).joins(:recordings => :recorded_tracks)
.where(%Q{ recordings.duration IS NOT NULL })
.where("recorded_tracks.user_id = '#{user.id}'")
.where(%Q{ recorded_tracks.fully_uploaded = FALSE }).each do |user|
user.recordings.each.do |recording|
recording.recorded_tracks.each do |recorded_track|
files.push(
{
:type => "recorded_track",
:id => recorded_track.client_track_id,
:url => recorded_track.url # FIXME IS THIS RIGHT?
}
)
end
end
files
end
def self.list_downloads(user, limit = 100, since = 0)
since = 0 unless since || since == '' # guard against nil
downloads = []
# That second join is important. It's saying join off of recordings, NOT user. If you take out the
# ":recordings =>" part, you'll just get the recorded_tracks that I played. Very different!
User.joins(:recordings).joins(:recordings => :recorded_tracks)
.order(%Q{ recorded_tracks.id })
.where(%Q{ recorded_tracks.fully_uploaded = TRUE })
# we also only allow you to be told about downloads if you have claimed the recording
#User.joins(:recordings).joins(:recordings => :recorded_tracks).joins(:recordings => :claimed_recordings)
RecordedTrack.joins(:recording).joins(:recording => :claimed_recordings)
.order('recorded_tracks.id')
.where('recorded_tracks.fully_uploaded = TRUE')
.where('recorded_tracks.id > ?', since)
.where(:id => user.id).limit(limit).each do |theuser|
theuser.recordings.each do |recording|
recording.recorded_tracks.each do |recorded_track|
# recorded_track = user.claimed_recordings.first.recording.recorded_tracks.first
downloads.push(
{
:type => "recorded_track",
:id => recorded_track.client_track_id,
:recording_id => recording.id,
:length => recorded_track.length,
:md5 => recorded_track.md5,
:url => recorded_track.filename,
:next => recorded_track.id
}
)
end
end
.where('claimed_recordings.user_id = ?', user).limit(limit).each do |recorded_track|
downloads.push(
{
:type => "recorded_track",
:id => recorded_track.client_track_id,
:recording_id => recorded_track.recording_id,
:length => recorded_track.length,
:md5 => recorded_track.md5,
:url => recorded_track.url,
:next => recorded_track.id
}
)
end
latest_recorded_track = downloads[-1][:next] if downloads.length > 0
# HOW TO LIMIT ON USER
User.joins(:recordings).joins(:recordings => :mixes)
Mix.joins(:recording).joins(:recording => :claimed_recordings)
.order('mixes.id')
.where('mixes.completed_at IS NOT NULL')
.where('mixes.id > ?', since)
.limit(limit).each do |theuser|
theuser.recordings.each do |recording|
recording.mixes.each do |mix|
downloads.push(
{
:type => "mix",
:id => mix.id,
:recording_id => recording.id,
:length => mix.length,
:md5 => mix.md5,
:url => mix.filename,
:created_at => mix.created_at,
:next => mix.id
}
)
end
end
.where('claimed_recordings.user_id = ?', user)
.limit(limit).each do |mix|
downloads.push(
{
:type => "mix",
:id => mix.id,
:recording_id => mix.recording_id,
:length => mix.length,
:md5 => mix.md5,
:url => mix.url,
:created_at => mix.created_at,
:next => mix.id
}
)
end
latest_mix = downloads[-1][:next] if downloads.length > 0

View File

@ -39,6 +39,7 @@ module JamRuby
has_many :owned_recordings, :class_name => "JamRuby::Recording"
has_many :recordings, :through => :claimed_recordings, :class_name => "JamRuby::Recording"
has_many :claimed_recordings, :class_name => "JamRuby::ClaimedRecording", :inverse_of => :user
has_many :playing_claimed_recordings, :class_name => "JamRuby::MusicSession", :inverse_of => :claimed_recording_initiator
# user likers (a musician has likers and may have likes too; fans do not have likers)
has_many :likers, :class_name => "JamRuby::UserLiker", :foreign_key => "user_id", :inverse_of => :user
@ -548,6 +549,28 @@ module JamRuby
self.save
end
def create_user_following(user_id)
follower = UserFollower.new
follower.user_id = user_id
follower.follower_id = self.id
follower.save
# TODO: make this async
user = User.find(user_id)
Notification.send_new_user_follower(self, user)
end
def create_band_following(band_id)
follower = BandFollower.new
follower.band_id = band_id
follower.follower_id = self.id
follower.save
# TODO: make this async
band = Band.find(band_id)
Notification.send_new_band_follower(self, band)
end
def self.finalize_update_email(update_email_token)
# updates the user model to have a new email address
user = User.find_by_update_email_token!(update_email_token)
@ -560,7 +583,6 @@ module JamRuby
return user
end
def self.create_user_like(user_id, liker_id)
liker = UserLiker.new()
liker.user_id = user_id
@ -578,7 +600,7 @@ module JamRuby
end
def self.create_band_like(band_id, liker_id)
liker = BandLiker.new()
liker = BandLiker.new
liker.band_id = band_id
liker.liker_id = liker_id
liker.save
@ -588,13 +610,6 @@ module JamRuby
JamRuby::BandLiker.delete_all "(band_id = '#{band_id}' AND liker_id = '#{liker_id}')"
end
def self.create_user_following(user_id, follower_id)
follower = UserFollower.new()
follower.user_id = user_id
follower.follower_id = follower_id
follower.save
end
def self.delete_following(user_id, band_id, follower_id)
if !user_id.nil?
JamRuby::UserFollower.delete_all "(user_id = '#{user_id}' AND follower_id = '#{follower_id}')"
@ -604,19 +619,12 @@ module JamRuby
end
end
def self.create_band_following(band_id, follower_id)
follower = BandFollower.new()
follower.band_id = band_id
follower.follower_id = follower_id
follower.save
end
def self.delete_band_following(band_id, follower_id)
JamRuby::BandFollower.delete_all "(band_id = '#{band_id}' AND follower_id = '#{follower_id}')"
end
def self.create_favorite(user_id, recording_id)
favorite = UserFavorite.new()
favorite = UserFavorite.new
favorite.user_id = user_id
favorite.recording_id = recording_id
favorite.save

View File

@ -89,7 +89,7 @@ class MQRouter
def publish_to_friends(friend_ids, user_msg, from_user_id)
EM.schedule do
friend_ids.each do |friend_id|
@@log.debug "publishing to friend:#{friend_id} from user #{from_user_id}"
@@log.debug "publishing to friend:#{friend_id} from user/band #{from_user_id}"
# put it on the topic exchange for users
self.class.user_exchange.publish(user_msg, :routing_key => "user.#{friend_id}")
end

View File

@ -0,0 +1,57 @@
require 'json'
require 'resque'
module JamRuby
@queue = :audiomixer
class AudioMixer
@@log = Logging.logger[AudioMixer]
def self.perform(manifest)
audiomixer = AudioMixer.new
audiomixer.run(manifest)
end
def initialize
end
def validate
raise "no files specified" if !@manifest[:files] || @manifest[:files].length == 0
end
def fetch_audio_files
@manifest[:files].each do |file|
filename = file[:filename]
end
end
def run(manifest)
@manifest = manifest.symbolize_keys
validate
fetch_audio_files
manifest_file = Dir::Tmpname.make_tmpname "/var/tmp/audiomixer/manifest-#{@manifest['recordingId']}", nil
File.open(manifest_file,"w") do |f|
f.write(@manifest.to_json)
end
#{"files": [{"codec": "vorbis", "offset": 0, "filename": "TPD - bass.flac-stereo.ogg"}, {"codec": "vorbis", "offset": 0, "filename": "TPD - bg vox.flac-stereo.ogg"}, {"codec": "vorbis", "offset": 0, "filename": "TPD - drums.flac-stereo.ogg"}, {"codec": "vorbis", "offset": 0, "filename": "TPD - guitars.flac-stereo.ogg"}, {"codec": "vorbis", "offset": 0, "filename": "TPD - lead vox.flac-stereo.ogg"}], "output": {"codec": "vorbis", "filename": "mix.ogg"}, "timeline": [{"timestamp": 0, "mix": [{"balance": 0, "level": 100}, {"balance": 0, "level": 100}, {"balance": 0, "level": 100}, {"balance": 0, "level": 100}, {"balance": 0, "level": 100}]}]}
audiomixer_cmd = "#{APP_CONFIG.audiomixer_path} #{manifest_file}"
@@log.debug("executing #{audiomixer_cmd}")
system(audiomixer_cmd)
end
end
end

View File

@ -32,6 +32,7 @@ FactoryGirl.define do
approval_required false
musician_access true
legal_terms true
genres [JamRuby::Genre.first]
association :creator, :factory => :user
end

View File

@ -1,13 +0,0 @@
require 'spec_helper'
describe S3Util do
describe "sign_url" do
pending
it "returns something" do
S3Util.sign_url("jamkazam-dev", "avatar-tmp/user/image.png").should_not be_nil
end
end
end

View File

@ -0,0 +1,115 @@
require 'spec_helper'
def valid_claimed_recording
@name = "hello"
@description = "description"
@genre = Genre.first
@is_public = true
@is_downloadable = true
end
def make_claim
@claimed_recording = @recording.claim(@user, @name, @description, @genre, @is_public, @is_downloadable)
end
describe ClaimedRecording do
before(:each) do
@user = FactoryGirl.create(:user)
@connection = FactoryGirl.create(:connection, :user => @user)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@music_session.connections << @connection
@music_session.save
@recording = Recording.start(@music_session, @user)
@recording.stop
@recording.reload
end
describe "sucessful save" do
it "with default case" do
valid_claimed_recording
make_claim
@claimed_recording.errors.any?.should be_false
@recording.reload
@recording.recorded_tracks.first.discard.should be_false
end
end
describe "update name" do
it "with nil" do
valid_claimed_recording
@name = nil
make_claim
@claimed_recording.errors.any?.should be_true
@claimed_recording.errors[:name].length.should == 2
@claimed_recording.errors[:name].select { |value| value.include?("can't be blank") }.length.should == 1
@claimed_recording.errors[:name].select { |value| value.include?("is too short") }.length.should == 1
@recording.reload
@recording.recorded_tracks.first.discard.should be_nil
end
it "too short" do
valid_claimed_recording
@name = "a"
make_claim
@claimed_recording.errors.any?.should be_true
@claimed_recording.errors[:name].length.should == 1
@claimed_recording.errors[:name].select { |value| value.include?("is too short") }.length.should == 1
end
end
describe "update description" do
it "with nil" do
valid_claimed_recording
@description = nil
make_claim
@claimed_recording.errors.any?.should be_false
end
end
describe "update is_public" do
it "with nil" do
valid_claimed_recording
@is_public = nil
make_claim
@claimed_recording.errors.any?.should be_true
@claimed_recording.errors[:is_public].length.should == 1
@claimed_recording.errors[:is_public].should == ["is not included in the list"]
end
end
describe "update is_downloadable" do
it "with nil" do
valid_claimed_recording
@is_downloadable = nil
make_claim
@claimed_recording.errors.any?.should be_true
@claimed_recording.errors[:is_downloadable].length.should == 1
@claimed_recording.errors[:is_downloadable].should == ["is not included in the list"]
end
end
describe "update genre" do
it "with nil" do
valid_claimed_recording
@genre = nil
make_claim
@claimed_recording.errors.any?.should be_true
@claimed_recording.errors[:genre].length.should == 1
@claimed_recording.errors[:genre].should == ["can't be blank"]
end
end
describe "multiple claims" do
it "not valid" do
valid_claimed_recording
make_claim
duplicate = @recording.claim(@user, "name", "description", @genre, true, true)
duplicate.valid?.should be_false
duplicate.errors[:recording_id].should == ['has already been taken']
end
end
end

View File

@ -0,0 +1,15 @@
require 'spec_helper'
describe IcecastAdminAuthentication do
let(:admin) { IcecastAdminAuthentication.new }
before(:all) do
end
it "save" do
admin.save.should be_true
end
end

View File

@ -0,0 +1,20 @@
require 'spec_helper'
describe IcecastLimit do
let(:limit) { IcecastLimit.new }
before(:all) do
end
it "save" do
limit.save.should be_true
end
it "non-integer clients should be checked" do
limit.clients = "a"
limit.save.should be_false
limit.errors[:clients].should == ['is not a number']
end
end

View File

@ -11,6 +11,8 @@ describe Mix do
@music_session.save
@recording = Recording.start(@music_session, @user)
@recording.stop
@recording.claim(@user, "name", "description", Genre.first, true, true)
@recording.errors.any?.should be_false
@mix = Mix.schedule(@recording, "{}")
end
@ -62,6 +64,23 @@ describe Mix do
@mix.sign_url.should_not be_nil
end
it "mixes are restricted by user" do
@mix.finish(1, "abc")
@mix.reload
@mix.errors.any?.should be_false
@user2 = FactoryGirl.create(:user)
recordings = Recording.list_downloads(@user)["downloads"]
recordings.length.should == 1
recordings[0][:type].should == "mix"
recordings[0][:id].should == @mix.id
recordings = Recording.list_downloads(@user2)["downloads"]
recordings.length.should == 0
end
end

View File

@ -430,7 +430,54 @@ describe MusicSession do
it "stop_recording should return recording object if recording" do
@music_session.stop_recording.should == @recording
end
end
describe "claim a recording" do
before(:each) do
@recording = Recording.start(@music_session, @user1)
@recording.errors.any?.should be_false
@recording.stop
@recording.reload
@claimed_recording = @recording.claim(@user1, "name", "description", Genre.first, true, true)
@claimed_recording.errors.any?.should be_false
end
it "allow a claimed recording to be associated" do
@music_session.claimed_recording_start(@user1, @claimed_recording)
@music_session.errors.any?.should be_false
@music_session.reload
@music_session.claimed_recording.should == @claimed_recording
@music_session.claimed_recording_initiator.should == @user1
end
it "allow a claimed recording to be removed" do
@music_session.claimed_recording_start(@user1, @claimed_recording)
@music_session.errors.any?.should be_false
@music_session.claimed_recording_stop
@music_session.errors.any?.should be_false
@music_session.reload
@music_session.claimed_recording.should be_nil
@music_session.claimed_recording_initiator.should be_nil
end
it "disallow a claimed recording to be started when already started by someone else" do
@user2 = FactoryGirl.create(:user)
@music_session.claimed_recording_start(@user1, @claimed_recording)
@music_session.errors.any?.should be_false
@music_session.claimed_recording_start(@user2, @claimed_recording)
@music_session.errors.any?.should be_true
@music_session.errors[:claimed_recording] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS]
end
it "allow a claimed recording to be started when already started by self" do
@user2 = FactoryGirl.create(:user)
@claimed_recording2 = @recording.claim(@user1, "name", "description", Genre.first, true, true)
@music_session.claimed_recording_start(@user1, @claimed_recording)
@music_session.errors.any?.should be_false
@music_session.claimed_recording_start(@user1, @claimed_recording2)
@music_session.errors.any?.should be_false
end
end
end
end

View File

@ -42,7 +42,7 @@ describe RecordedTrack do
it "gets a url for the track" do
@recorded_track = RecordedTrack.create_from_track(@track, @recording)
@recorded_track.save.should be_true
@recorded_track.url.should == "recordings/#{@recording.id}/track-#{@track.id}.ogg"
@recorded_track.url.should == "recordings/#{@recording.id}/track-#{@track.client_track_id}.ogg"
end
it "signs url" do
@ -51,6 +51,18 @@ describe RecordedTrack do
@recorded_track.sign_url.should_not be_nil
end
it "can not be downloaded if no claimed recording" do
user2 = FactoryGirl.create(:user)
@recorded_track = RecordedTrack.create_from_track(@track, @recording)
@recorded_track.can_download?(user2).should be_false
@recorded_track.can_download?(@user).should be_false
end
it "can be downloaded if there is a claimed recording" do
@recorded_track = RecordedTrack.create_from_track(@track, @recording)
@recording.claim(@user, "my recording", "my description", Genre.first, true, true).errors.any?.should be_false
@recorded_track.can_download?(@user).should be_true
end
describe "aws-based operations", :aws => true do

View File

@ -8,7 +8,26 @@ describe Recording do
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@connection = FactoryGirl.create(:connection, :user => @user, :music_session => @music_session)
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
end
end
it "should allow finding of recorded tracks" do
user2 = FactoryGirl.create(:user)
connection2 = FactoryGirl.create(:connection, :user => user2, :music_session => @music_session)
track2 = FactoryGirl.create(:track, :connection => connection2, :instrument => @instrument)
@recording = Recording.start(@music_session, @user)
user1_recorded_tracks = @recording.recorded_tracks_for_user(@user)
user1_recorded_tracks[0].should == @user.recorded_tracks[0]
user1_recorded_tracks.length.should == 1
user2_recorded_tracks = @recording.recorded_tracks_for_user(user2)
user2_recorded_tracks.length.should == 1
user2_recorded_tracks[0].should == user2.recorded_tracks[0]
RecordedTrack.update(user1_recorded_tracks, :discard => true)
user1_recorded_tracks[0].reload
user1_recorded_tracks[0].discard.should be_true
end
it "should set up the recording properly when recording is started with 1 user in the session" do
@music_session.is_recording?.should be_false
@ -50,6 +69,7 @@ describe Recording do
it "should be able to start, stop then start a recording again for the same music session" do
@recording = Recording.start(@music_session, @user)
@recording.stop
@recording.keep(@user)
@recording2 = Recording.start(@music_session, @user)
@music_session.recordings.exists?(@recording2).should be_true
end
@ -118,16 +138,6 @@ describe Recording do
expect { @recording.claim(user2, "name", "description", @genre, true, true) }.to raise_error
end
it "should fail if a user tries to claim a recording twice" do
@recording = Recording.start(@music_session, @user)
@recording.stop
@recording.reload
@genre = FactoryGirl.create(:genre)
@recording.claim(@user, "name", "description", @genre, true, true)
@recording.reload
expect { @recording.claim(@user, "name", "description", @genre, true, true) }.to raise_error
end
it "should allow editing metadata for claimed recordings" do
@recording = Recording.start(@music_session, @user)
@recording.stop
@ -206,6 +216,21 @@ describe Recording do
Recording.list_uploads(@user, 10, uploads["next"])["uploads"].length.should == 0
end
it "should return a download only if claimed" do
@recording = Recording.start(@music_session, @user)
@recording.stop
@recording.reload
@genre = FactoryGirl.create(:genre)
@recording.claim(@user, "Recording", "Recording Description", @genre, true, true)
downloads = Recording.list_downloads(@user)
downloads["downloads"].length.should == 0
@recorded_track = RecordedTrack.where(:recording_id => @recording.id)[0]
@recorded_track.update_attribute(:fully_uploaded, true)
downloads = Recording.list_downloads(@user)
downloads["downloads"].length.should == 1
end
it "should return a file list for a user properly" do
pending
stub_const("APP_CONFIG", app_config)
@ -292,6 +317,45 @@ describe Recording do
timeline.last["timestamp"].should == @recording.duration
timeline.last["end"].should == true
end
describe "chance for everyone to keep or discard" do
before(:each) do
@user2 = FactoryGirl.create(:user)
@connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session)
@track2 = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument)
@recording = Recording.start(@music_session, @user)
@recording.stop
@recording.reload
end
it "no one votes" do
@recording2 = Recording.start(@music_session, @user)
@recording2.errors.any?.should be_true
@recording2.errors[:music_session].should == [ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED]
end
it "only one discards" do
@recording.discard(@user)
@recording2 = Recording.start(@music_session, @user)
@recording2.errors.any?.should be_true
@recording2.errors[:music_session].should == [ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED]
end
it "everyone discards" do
@recording.discard(@user)
@recording.discard(@user2)
@recording2 = Recording.start(@music_session, @user)
@recording2.errors.any?.should be_false
end
it "one discards, the other leaves the session" do
@recording.discard(@user)
@connection2.delete
@recording2 = Recording.start(@music_session, @user2)
@recording2.errors.any?.should be_false
end
end
end

View File

@ -31,12 +31,25 @@ describe MQRouter do
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")
# this is necessary because other tests will call EM.schedule indirectly as they fiddle with AR models, since some of our
# notifications are tied to model activity. So, the issue here is that you'll have an unknown known amount of
# queued up messages ready to be sent to MQRouter (because EM.schedule will put deferred blocks onto @next_tick_queue),
# resulting in messages from other tests being sent to client_exchange or user_exchange
# there is no API I can see to clear out the EM queue. so just open up the EM module and do it manually
module EM
@next_tick_queue = []
end
EM.run do
# mock up exchange
MQRouter.client_exchange = double("client_exchange")
MQRouter.user_exchange = double("user_exchange")
MQRouter.client_exchange.should_receive(:publish).with("a message", :routing_key => "client.#{music_session_member2.client_id}")
MQRouter.user_exchange.should_not_receive(:publish)
@mq_router.user_publish_to_session(music_session, user1, "a message", :client_id => music_session_member1.client_id)

View File

@ -0,0 +1,18 @@
require 'spec_helper'
# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests
describe AudioMixer do
let(:audiomixer) { AudioMixer.new }
describe "validate" do
it "no files specified" do
expect{ audiomixer.run({}) }.to raise_error("no files specified")
end
it "no codec specified" do
expect{ audiomixer.run({ "files" => [ "offset" => 0, "filename" => "/some/path"] }) }
end
end
end

View File

@ -78,6 +78,10 @@ Spork.prefork do
DatabaseCleaner.clean
end
config.after(:suite) do
wipe_s3_test_bucket
end
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.

View File

@ -1,8 +1,9 @@
JAMKAZAM_TESTING_BUCKET = 'jamkazam-testing' # cuz i'm not comfortable using aws_bucket accessor directly
def app_config
klass = Class.new do
def aws_bucket
'jamkazam-testing'
JAMKAZAM_TESTING_BUCKET
end
def aws_access_key_id
@ -12,7 +13,38 @@ def app_config
def aws_secret_access_key
'h0V0ffr3JOp/UtgaGrRfAk25KHNiO9gm8Pj9m6v3'
end
def audiomixer_path
# you can specify full path to audiomixer with AUDIOMIXER_PATH env variable...
# or we check for audiomixer path in the user's workspace
# and finally the debian install path
ENV['AUDIOMIXER_PATH'] || audiomixer_workspace_path || "/var/lib/audiomixer/audiomixer/audiomixerapp"
end
private
def audiomixer_workspace_path
if ENV['WORKSPACE']
dev_path = ENV['WORKSPACE']
else
dev_path = ENV['HOME']
end
dev_path = "#{dev_path}/audiomixer/audiomixer/audiomixerapp"
dev_path if File.exist? dev_path
end
end
return klass.new
end
def wipe_s3_test_bucket
test_config = app_config
s3 = AWS::S3.new(:access_key_id => test_config.aws_access_key_id,
:secret_access_key => test_config.aws_secret_access_key)
test_bucket = s3.buckets[JAMKAZAM_TESTING_BUCKET]
if test_bucket.name == JAMKAZAM_TESTING_BUCKET
#test_bucket.clear!
end
end

1
runweb
View File

@ -1,5 +1,6 @@
#!/bin/bash
pushd web
# run jam-web rails server
bundle exec rails s
popd

2
update
View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash
set -e

View File

@ -1 +1 @@
ruby-2.0.0-p247
2.0.0-p247

View File

@ -18,9 +18,10 @@ else
gem 'jam_ruby', "0.1.#{ENV["BUILD_NUMBER"]}"
gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}"
end
gem 'builder'
gem 'rails', '>=3.2.11'
gem 'jquery-rails', '2.0.2'
gem 'jquery-ui-rails'
gem 'bootstrap-sass', '2.0.4'
gem 'bcrypt-ruby', '3.0.1'
gem 'faker', '1.0.1'
@ -32,7 +33,7 @@ gem 'ruby-protocol-buffers', '1.2.2'
gem 'pg', '0.15.1'
gem 'compass-rails'
gem 'rabl' # for JSON API development
gem 'gon' # for passthrough of Ruby variables to Javascript variables
gem 'gon', '~>4.1.0' # for passthrough of Ruby variables to Javascript variables
gem 'eventmachine', '1.0.3'
gem 'amqp', '0.9.8'
gem 'logging-rails', :require => 'logging/rails'
@ -57,6 +58,7 @@ gem 'postgres-copy'
gem 'geokit-rails'
gem 'postgres_ext'
gem 'haml-rails'
gem 'resque'
gem 'quiet_assets', :group => :development
@ -64,6 +66,7 @@ gem "bugsnag"
group :development, :test do
gem 'rspec-rails'
gem "activerecord-import", "~> 0.4.1"
gem 'guard-rspec', '0.5.5'
gem 'jasmine', '1.3.1'
gem 'pry'

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -12,22 +12,42 @@
LOGIN_ACK : "LOGIN_ACK",
LOGIN_MUSIC_SESSION : "LOGIN_MUSIC_SESSION",
LOGIN_MUSIC_SESSION_ACK : "LOGIN_MUSIC_SESSION_ACK",
FRIEND_SESSION_JOIN : "FRIEND_SESSION_JOIN",
MUSICIAN_SESSION_JOIN : "MUSICIAN_SESSION_JOIN",
MUSICIAN_SESSION_DEPART : "MUSICIAN_SESSION_DEPART",
LEAVE_MUSIC_SESSION : "LEAVE_MUSIC_SESSION",
LEAVE_MUSIC_SESSION_ACK : "LEAVE_MUSIC_SESSION_ACK",
HEARTBEAT : "HEARTBEAT",
HEARTBEAT_ACK : "HEARTBEAT_ACK",
// friend notifications
FRIEND_UPDATE : "FRIEND_UPDATE",
FRIEND_REQUEST : "FRIEND_REQUEST",
FRIEND_REQUEST_ACCEPTED : "FRIEND_REQUEST_ACCEPTED",
FRIEND_SESSION_JOIN : "FRIEND_SESSION_JOIN",
NEW_USER_FOLLOWER : "NEW_USER_FOLLOWER",
NEW_BAND_FOLLOWER : "NEW_BAND_FOLLOWER",
// session notifications
SESSION_INVITATION : "SESSION_INVITATION",
SESSION_ENDED : "SESSION_ENDED",
JOIN_REQUEST : "JOIN_REQUEST",
JOIN_REQUEST_APPROVED : "JOIN_REQUEST_APPROVED",
JOIN_REQUEST_REJECTED : "JOIN_REQUEST_REJECTED",
FRIEND_REQUEST : "FRIEND_REQUEST",
FRIEND_REQUEST_ACCEPTED : "FRIEND_REQUEST_ACCEPTED",
SESSION_JOIN : "SESSION_JOIN",
SESSION_DEPART : "SESSION_DEPART",
MUSICIAN_SESSION_JOIN : "MUSICIAN_SESSION_JOIN",
BAND_SESSION_JOIN : "BAND_SESSION_JOIN",
// recording notifications
MUSICIAN_RECORDING_SAVED : "MUSICIAN_RECORDING_SAVED",
BAND_RECORDING_SAVED : "BAND_RECORDING_SAVED",
RECORDING_STARTED : "RECORDING_STARTED",
RECORDING_ENDED : "RECORDING_ENDED",
RECORDING_MASTER_MIX_COMPLETE : "RECORDING_MASTER_MIX_COMPLETE",
DOWNLOAD_AVAILABLE : "DOWNLOAD_AVAILABLE",
// band notifications
BAND_INVITATION : "BAND_INVITATION",
BAND_INVITATION_ACCEPTED : "BAND_INVITATION_ACCEPTED",
TEST_SESSION_MESSAGE : "TEST_SESSION_MESSAGE",
PING_REQUEST : "PING_REQUEST",
PING_ACK : "PING_ACK",
@ -84,10 +104,10 @@
// reconnect_music_session_id is an optional argument that allows the session to be immediately associated
// with a music session.
factory.login_with_token = function(token, reconnect_music_session_id) {
//context.JK.logger.debug("*** login_with_token: client_id = "+$.cookie("client_id"));
//context.JK.logger.debug("*** login_with_token: client_id = "+$.cookie("client_id"));
var login = { token : token,
client_id : $.cookie("client_id")
};
client_id : $.cookie("client_id")
};
return client_container(msg.LOGIN, route_to.SERVER, login);
};

View File

@ -21,7 +21,7 @@
server.connected = false;
// handles logic if the websocket connection closes, and if it was in error then also prompt for reconnect
// handles logic if the websocket connection closes, and if it was in error then also prompt for reconnect
function closedCleanup(in_error) {
if(server.connected) {
server.connected = false;
@ -61,10 +61,10 @@
break;
}
}
}
if (server.dispatchTable[messageType].length === 0) {
delete server.dispatchTable[messageType];
if (server.dispatchTable[messageType].length === 0) {
delete server.dispatchTable[messageType];
}
}
};

Some files were not shown because too many files have changed in this diff Show More