resolve conflict
This commit is contained in:
commit
57a9571483
|
|
@ -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"
|
||||
|
|
|
|||
57
db/jenkins
57
db/jenkins
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -81,4 +81,7 @@ notification_band_invite.sql
|
|||
band_photo_filepicker.sql
|
||||
bands_geocoding.sql
|
||||
store_s3_filenames.sql
|
||||
icecast.sql
|
||||
icecast.sql
|
||||
discardable_recorded_tracks.sql
|
||||
music_sessions_have_claimed_recording.sql
|
||||
discardable_recorded_tracks2.sql
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE recorded_tracks ALTER COLUMN discard DROP DEFAULT;
|
||||
ALTER TABLE recorded_tracks ALTER COLUMN discard DROP NOT NULL;
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -9,43 +9,61 @@ 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;
|
||||
|
||||
// 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 +77,64 @@ 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;
|
||||
|
||||
// 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 +194,157 @@ 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 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 +365,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 +407,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.
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New Band Invitation') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'Band Invitation Accepted') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New Band Recording') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New Band Session') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New JamKazam Friend Request') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'Friend Request Accepted') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New Musician Recording') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'Musician in Session') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New Band Follower on JamKazam') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'New Follower on JamKazam') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'Recording Master Mix Completed') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<% provide(:title, 'Session Invitation') %>
|
||||
|
||||
<p><%= @body %></p>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<%= @body %>
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = {})
|
||||
|
|
@ -114,6 +114,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 +148,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 +159,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 +194,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 +533,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 +584,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 +608,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,47 @@ 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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,46 +155,22 @@ 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)
|
||||
|
||||
# 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)
|
||||
.order(%Q{ recorded_tracks.id })
|
||||
.where(%Q{ recorded_tracks.fully_uploaded = TRUE })
|
||||
.where('recorded_tracks.id > ?', since)
|
||||
.where('claimed_recordings.user_id = ?', user)
|
||||
.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",
|
||||
|
|
@ -159,7 +178,7 @@ module JamRuby
|
|||
:recording_id => recording.id,
|
||||
:length => recorded_track.length,
|
||||
:md5 => recorded_track.md5,
|
||||
:url => recorded_track.filename,
|
||||
:url => recorded_track.url,
|
||||
:next => recorded_track.id
|
||||
}
|
||||
)
|
||||
|
|
@ -169,11 +188,11 @@ module JamRuby
|
|||
|
||||
latest_recorded_track = downloads[-1][:next] if downloads.length > 0
|
||||
|
||||
# HOW TO LIMIT ON USER
|
||||
User.joins(:recordings).joins(:recordings => :mixes)
|
||||
.order('mixes.id')
|
||||
.where('mixes.completed_at IS NOT NULL')
|
||||
.where('mixes.id > ?', since)
|
||||
.where(:id => user.id)
|
||||
.limit(limit).each do |theuser|
|
||||
theuser.recordings.each do |recording|
|
||||
recording.mixes.each do |mix|
|
||||
|
|
@ -184,7 +203,7 @@ module JamRuby
|
|||
:recording_id => recording.id,
|
||||
:length => mix.length,
|
||||
:md5 => mix.md5,
|
||||
:url => mix.filename,
|
||||
:url => mix.url,
|
||||
:created_at => mix.created_at,
|
||||
:next => mix.id
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ FactoryGirl.define do
|
|||
approval_required false
|
||||
musician_access true
|
||||
legal_terms true
|
||||
genres [JamRuby::Genre.first]
|
||||
association :creator, :factory => :user
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -11,6 +11,7 @@ describe Mix do
|
|||
@music_session.save
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
@recording.stop
|
||||
@recording.claim(@user, "name", "description", Genre.first, true, true)
|
||||
@mix = Mix.schedule(@recording, "{}")
|
||||
end
|
||||
|
||||
|
|
@ -62,6 +63,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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,20 @@ 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 +316,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
|
||||
|
||||
|
||||
|
|
|
|||
1
runweb
1
runweb
|
|
@ -1,5 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
pushd web
|
||||
# run jam-web rails server
|
||||
bundle exec rails s
|
||||
popd
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ end
|
|||
|
||||
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'
|
||||
|
|
@ -64,6 +65,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 |
|
|
@ -12,22 +12,41 @@
|
|||
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",
|
||||
|
||||
// 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 +103,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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
city: userDetail.city,
|
||||
first_name: userDetail.first_name,
|
||||
last_name: userDetail.last_name,
|
||||
photoUrl: context.JK.resolveAvatarUrl(userDetail.photo_url),
|
||||
user_instruments: userDetail.instruments,
|
||||
birth_date : userDetail.birth_date,
|
||||
gender: userDetail.gender,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,14 @@
|
|||
//
|
||||
//= require jquery
|
||||
//= require jquery_ujs
|
||||
//= require jquery.ui.draggable
|
||||
//= require jquery.bt
|
||||
//= require jquery.icheck
|
||||
//= require jquery.color
|
||||
//= require jquery.cookie
|
||||
//= require jquery.Jcrop
|
||||
//= require jquery.naturalsize
|
||||
//= require jquery.queryparams
|
||||
//= require jquery.timeago
|
||||
//= require globals
|
||||
//= require_directory .
|
||||
|
|
|
|||
|
|
@ -11,21 +11,25 @@
|
|||
|
||||
var $draggingFaderHandle = null;
|
||||
var $draggingFader = null;
|
||||
var draggingOrientation = null;
|
||||
|
||||
var subscribers = {};
|
||||
var logger = g.JK.logger;
|
||||
var MAX_VISUAL_FADER = 95;
|
||||
|
||||
function faderClick(evt) {
|
||||
evt.stopPropagation();
|
||||
if (g.JK.$draggingFaderHandle) {
|
||||
return;
|
||||
function faderClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
var $fader = $(this);
|
||||
draggingOrientation = $fader.attr('orientation');
|
||||
var faderId = $fader.attr("fader-id");
|
||||
var offset = $fader.offset();
|
||||
var position = { top: e.pageY - offset.top, left: e.pageX - offset.left}
|
||||
|
||||
var faderPct = faderValue($fader, e, position);
|
||||
|
||||
if (faderPct < 0 || faderPct > 100) {
|
||||
return false;
|
||||
}
|
||||
var $fader = $(evt.currentTarget);
|
||||
var faderId = $fader.closest('[fader-id]').attr("fader-id");
|
||||
var $handle = $fader.find('div[control="fader-handle"]');
|
||||
|
||||
var faderPct = faderValue($fader, evt);
|
||||
|
||||
// Notify subscribers of value change
|
||||
g._.each(subscribers, function(changeFunc, index, list) {
|
||||
|
|
@ -39,75 +43,35 @@
|
|||
}
|
||||
|
||||
function setHandlePosition($fader, value) {
|
||||
if (value > MAX_VISUAL_FADER) { value = MAX_VISUAL_FADER; } // Visual limit
|
||||
var ratio, position;
|
||||
var $handle = $fader.find('div[control="fader-handle"]');
|
||||
var handleCssAttribute = getHandleCssAttribute($fader);
|
||||
$handle.css(handleCssAttribute, value + '%');
|
||||
}
|
||||
|
||||
|
||||
function faderHandleDown(evt) {
|
||||
evt.stopPropagation();
|
||||
$draggingFaderHandle = $(evt.currentTarget);
|
||||
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
|
||||
return false;
|
||||
}
|
||||
|
||||
function faderMouseUp(evt) {
|
||||
evt.stopPropagation();
|
||||
if ($draggingFaderHandle) {
|
||||
var $fader = $draggingFaderHandle.closest('div[control="fader"]');
|
||||
var faderId = $fader.closest('[fader-id]').attr("fader-id");
|
||||
var faderPct = faderValue($fader, evt);
|
||||
// Notify subscribers of value change
|
||||
g._.each(subscribers, function(changeFunc, index, list) {
|
||||
if (faderId === index) {
|
||||
changeFunc(faderId, faderPct, false);
|
||||
}
|
||||
});
|
||||
$draggingFaderHandle = null;
|
||||
$draggingFader = null;
|
||||
if(draggingOrientation === "horizontal") {
|
||||
ratio = value / 100;
|
||||
position = ((ratio * $fader.width()) - (ratio * handleWidth(draggingOrientation))) + 'px';
|
||||
}
|
||||
return false;
|
||||
else {
|
||||
ratio = (100 - value) / 100;
|
||||
position = ((ratio * $fader.height()) - (ratio * handleWidth(draggingOrientation))) + 'px';
|
||||
}
|
||||
$handle.css(handleCssAttribute, position);
|
||||
}
|
||||
|
||||
function faderValue($fader, evt) {
|
||||
function faderValue($fader, e, offset) {
|
||||
var orientation = $fader.attr('orientation');
|
||||
var getPercentFunction = getVerticalFaderPercent;
|
||||
var absolutePosition = evt.clientY;
|
||||
var relativePosition = offset.top;
|
||||
if (orientation && orientation == 'horizontal') {
|
||||
getPercentFunction = getHorizontalFaderPercent;
|
||||
absolutePosition = evt.clientX;
|
||||
relativePosition = offset.left;
|
||||
}
|
||||
return getPercentFunction(absolutePosition, $fader);
|
||||
return getPercentFunction(relativePosition, $fader);
|
||||
}
|
||||
|
||||
function getHandleCssAttribute($fader) {
|
||||
var orientation = $fader.attr('orientation');
|
||||
return (orientation === 'horizontal') ? 'left' : 'bottom';
|
||||
}
|
||||
|
||||
function faderMouseMove(evt) {
|
||||
// bail out early if there's no in-process drag
|
||||
if (!($draggingFaderHandle)) {
|
||||
return false;
|
||||
}
|
||||
var $fader = $draggingFader;
|
||||
var faderId = $fader.closest('[fader-id]').attr("fader-id"); var $handle = $draggingFaderHandle;
|
||||
evt.stopPropagation();
|
||||
var faderPct = faderValue($fader, evt);
|
||||
|
||||
// Notify subscribers of value change
|
||||
g._.each(subscribers, function(changeFunc, index, list) {
|
||||
if (faderId === index) {
|
||||
changeFunc(faderId, faderPct, true);
|
||||
}
|
||||
});
|
||||
|
||||
if (faderPct > MAX_VISUAL_FADER) { faderPct = MAX_VISUAL_FADER; } // Visual limit
|
||||
var handleCssAttribute = getHandleCssAttribute($fader);
|
||||
$handle.css(handleCssAttribute, faderPct + '%');
|
||||
return false;
|
||||
return (orientation === 'horizontal') ? 'left' : 'top';
|
||||
}
|
||||
|
||||
function getVerticalFaderPercent(eventY, $fader) {
|
||||
|
|
@ -119,28 +83,75 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the fader as int percent 0-100
|
||||
*/
|
||||
* Returns the current value of the fader as int percent 0-100
|
||||
*/
|
||||
function getFaderPercent(value, $fader, orientation) {
|
||||
var faderPosition = $fader.offset();
|
||||
var faderMin = faderPosition.top;
|
||||
var faderSize = $fader.height();
|
||||
var handleValue = (faderSize - (value-faderMin));
|
||||
var faderSize, faderPct;
|
||||
|
||||
// the handle takes up room, and all calculations use top. So when the
|
||||
// handle *looks* like it's at the bottom by the user, it won't give a 0% value.
|
||||
// so, we subtract handleWidth from the size of it's parent
|
||||
|
||||
if (orientation === "horizontal") {
|
||||
faderMin = faderPosition.left;
|
||||
faderSize = $fader.width();
|
||||
handleValue = (value - faderMin);
|
||||
faderPct = Math.round( ( value + (value / faderSize * handleWidth(orientation))) / faderSize * 100);
|
||||
}
|
||||
var faderPct = Math.round(handleValue/faderSize * 100);
|
||||
if (faderPct < 0) {
|
||||
faderPct = 0;
|
||||
}
|
||||
if (faderPct > 100) {
|
||||
faderPct = 100;
|
||||
else {
|
||||
faderSize = $fader.height();
|
||||
faderPct = Math.round((faderSize - handleWidth(orientation) - value)/(faderSize - handleWidth(orientation)) * 100);
|
||||
}
|
||||
|
||||
return faderPct;
|
||||
}
|
||||
|
||||
function onFaderDrag(e, ui) {
|
||||
var faderId = $draggingFader.attr("fader-id");
|
||||
var faderPct = faderValue($draggingFader, e, ui.position);
|
||||
|
||||
// protect against attempts to drag outside of the slider, which jquery.draggable sometimes allows
|
||||
if (faderPct < 0 || faderPct > 100) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Notify subscribers of value change
|
||||
g._.each(subscribers, function(changeFunc, index, list) {
|
||||
if (faderId === index) {
|
||||
changeFunc(faderId, faderPct, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onFaderDragStart(e, ui) {
|
||||
$draggingFaderHandle = $(this);
|
||||
$draggingFader = $draggingFaderHandle.closest('div[control="fader"]');
|
||||
draggingOrientation = $draggingFader.attr('orientation');
|
||||
}
|
||||
|
||||
function onFaderDragStop(e, ui) {
|
||||
var faderId = $draggingFader.attr("fader-id");
|
||||
var faderPct = faderValue($draggingFader, e, ui.position);
|
||||
|
||||
// protect against attempts to drag outside of the slider, which jquery.draggable sometimes allows
|
||||
// do not return 'false' though, because that stops future drags from working, for some reason
|
||||
if (faderPct < 0 || faderPct > 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify subscribers of value change
|
||||
g._.each(subscribers, function(changeFunc, index, list) {
|
||||
if (faderId === index) {
|
||||
changeFunc(faderId, faderPct, false);
|
||||
}
|
||||
});
|
||||
$draggingFaderHandle = null;
|
||||
$draggingFader = null;
|
||||
draggingOrientation = null;
|
||||
}
|
||||
|
||||
function handleWidth(orientation) {
|
||||
return orientation === "horizontal" ? 8 : 11;
|
||||
}
|
||||
|
||||
g.JK.FaderHelpers = {
|
||||
|
||||
/**
|
||||
|
|
@ -174,6 +185,15 @@
|
|||
var templateSource = $(templateSelector).html();
|
||||
|
||||
$(selector).html(g._.template(templateSource, options));
|
||||
|
||||
$('div[control="fader-handle"]', $(selector)).draggable({
|
||||
drag: onFaderDrag,
|
||||
start: onFaderDragStart,
|
||||
stop: onFaderDragStop,
|
||||
containment: "parent",
|
||||
axis: options.faderType === 'horizontal' ? 'x' : 'y'
|
||||
})
|
||||
|
||||
// Embed any custom styles, applied to the .fader below selector
|
||||
if ("style" in options) {
|
||||
for (var key in options.style) {
|
||||
|
|
@ -213,11 +233,6 @@
|
|||
|
||||
initialize: function() {
|
||||
$('body').on('click', 'div[control="fader"]', faderClick);
|
||||
$('body').on('mousedown', 'div[control="fader-handle"]', faderHandleDown);
|
||||
$('body').on('mousemove', 'div[layout-id="session"], [layout-wizard="ftue"]', faderMouseMove);
|
||||
$('body').on('mouseup', 'div[layout-id="session"], [layout-wizard="ftue"]', faderMouseUp);
|
||||
//$('body').on('mousemove', faderMouseMove);
|
||||
//$('body').on('mouseup', faderMouseUp);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -542,6 +542,28 @@
|
|||
|
||||
}
|
||||
|
||||
// passed an array of recording objects from the server
|
||||
function GetLocalRecordingState(recordings) {
|
||||
var result = { recordings:[]};
|
||||
var recordingResults = result.recordings;
|
||||
|
||||
var possibleAnswers = ['HQ', 'RT', 'MISSING', 'PARTIALLY_MISSING'];
|
||||
|
||||
$.each(recordings, function(i, recording) {
|
||||
// just make up a random yes-hq/yes-rt/missing answer
|
||||
var recordingResult = {};
|
||||
recordingResult['aggregate_state'] = possibleAnswers[Math.floor((Math.random()*4))];
|
||||
recordingResults.push(recordingResult);
|
||||
})
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function OpenRecording(claimedRecording) {
|
||||
return {success: true}
|
||||
}
|
||||
function CloseRecording() {}
|
||||
|
||||
|
||||
// Javascript Bridge seems to camel-case
|
||||
// Set the instance functions:
|
||||
|
|
@ -663,6 +685,11 @@
|
|||
this.OnLoggedIn = OnLoggedIn;
|
||||
this.OnLoggedOut = OnLoggedOut;
|
||||
|
||||
// Recording Playback
|
||||
this.GetLocalRecordingState = GetLocalRecordingState;
|
||||
this.OpenRecording = OpenRecording;
|
||||
this.CloseRecording = CloseRecording;
|
||||
|
||||
// fake calls; not a part of the actual jam client
|
||||
this.RegisterP2PMessageCallbacks = RegisterP2PMessageCallbacks;
|
||||
this.SetFakeRecordingImpl = SetFakeRecordingImpl;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
$.each(genreList, function(index, value) {
|
||||
values.push(value.toLowerCase());
|
||||
});
|
||||
console.log("OH HAI O")
|
||||
var selectedVal = $('select', parentSelector).val(values);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -504,6 +504,71 @@
|
|||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: "/api/recordings/" + recordingId
|
||||
});
|
||||
}
|
||||
|
||||
function getClaimedRecordings(options) {
|
||||
|
||||
return $.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: "/api/claimed_recordings",
|
||||
data: options
|
||||
});
|
||||
}
|
||||
|
||||
function claimRecording(options) {
|
||||
var recordingId = options["id"];
|
||||
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: "/api/recordings/" + recordingId + "/claim",
|
||||
data: JSON.stringify(options)
|
||||
})
|
||||
}
|
||||
|
||||
function startPlayClaimedRecording(options) {
|
||||
var musicSessionId = options["id"];
|
||||
var claimedRecordingId = options["claimed_recording_id"];
|
||||
delete options["id"];
|
||||
delete options["claimed_recording_id"];
|
||||
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: "/api/sessions/" + musicSessionId + "/claimed_recording/" + claimedRecordingId + "/start",
|
||||
data: JSON.stringify(options)
|
||||
})
|
||||
}
|
||||
|
||||
function stopPlayClaimedRecording(options) {
|
||||
var musicSessionId = options["id"];
|
||||
var claimedRecordingId = options["claimed_recording_id"];
|
||||
delete options["id"];
|
||||
delete options["claimed_recording_id"];
|
||||
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: "/api/sessions/" + musicSessionId + "/claimed_recording/" + claimedRecordingId + "/stop",
|
||||
data: JSON.stringify(options)
|
||||
})
|
||||
}
|
||||
|
||||
function discardRecording(options) {
|
||||
var recordingId = options["id"];
|
||||
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
url: "/api/recordings/" + recordingId + "/discard",
|
||||
data: JSON.stringify(options)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -541,7 +606,7 @@
|
|||
this.getFriends = getFriends;
|
||||
this.updateSession = updateSession;
|
||||
this.getSession = getSession;
|
||||
this.getClientDownloads = getClientDownloads
|
||||
this.getClientDownloads = getClientDownloads;
|
||||
this.createInvitation = createInvitation;
|
||||
this.postFeedback = postFeedback;
|
||||
this.serverHealthCheck = serverHealthCheck;
|
||||
|
|
@ -556,6 +621,11 @@
|
|||
this.startRecording = startRecording;
|
||||
this.stopRecording = stopRecording;
|
||||
this.getRecording = getRecording;
|
||||
this.getClaimedRecordings = getClaimedRecordings;
|
||||
this.claimRecording = claimRecording;
|
||||
this.startPlayClaimedRecording = startPlayClaimedRecording;
|
||||
this.stopPlayClaimedRecording = stopPlayClaimedRecording;
|
||||
this.discardRecording = discardRecording;
|
||||
this.putTrackSyncChange = putTrackSyncChange;
|
||||
this.createBand = createBand;
|
||||
this.updateBand = updateBand;
|
||||
|
|
|
|||
|
|
@ -264,6 +264,23 @@
|
|||
this.notify({title:title, text:text, icon_url: "/assets/content/icon_alert_big.png"});
|
||||
}
|
||||
|
||||
/** Using the standard rails style error object, shows an alert with all seen errors */
|
||||
this.notifyServerError = function(jqXHR, title) {
|
||||
if(!title) {
|
||||
title = "Server Error";
|
||||
}
|
||||
if(jqXHR.status == 422) {
|
||||
var errors = JSON.parse(jqXHR.responseText);
|
||||
var $errors = context.JK.format_all_errors(errors);
|
||||
this.notify({title:title, text:$errors, icon_url: "/assets/content/icon_alert_big.png"})
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to cehck more status codes and make tailored messages at this point
|
||||
this.notify({title:title, text:"status=" + jqXHR.status + ", message=" + jqXHR.responseText, icon_url: "/assets/content/icon_alert_big.png"})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize any common events.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@
|
|||
function setNotificationInfo(message, descriptor) {
|
||||
var $notify = $('[layout="notify"]');
|
||||
$('h2', $notify).text(message.title);
|
||||
$('p', $notify).html(message.text);
|
||||
$('p', $notify).html(message.text instanceof jQuery ? message.text.html() : message.text);
|
||||
|
||||
if (message.icon_url) {
|
||||
$('#avatar', $notify).attr('src', message.icon_url);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
(function(context,$) {
|
||||
|
||||
"use strict";
|
||||
context.JK = context.JK || {};
|
||||
context.JK.LocalRecordingsDialog = function(app) {
|
||||
var logger = context.JK.logger;
|
||||
var rest = context.JK.Rest();
|
||||
var showing = false;
|
||||
var perPage = 10;
|
||||
|
||||
function tbody() {
|
||||
return $('#local-recordings-dialog table.local-recordings tbody');
|
||||
}
|
||||
|
||||
function emptyList() {
|
||||
tbody().empty();
|
||||
}
|
||||
|
||||
function resetPagination() {
|
||||
$('#local-recordings-dialog .paginator').remove();
|
||||
}
|
||||
|
||||
|
||||
function beforeShow() {
|
||||
emptyList();
|
||||
resetPagination();
|
||||
showing = true;
|
||||
getRecordings(0)
|
||||
.done(function(data, textStatus, jqXHR) {
|
||||
// initialize pagination
|
||||
var $paginator = context.JK.Paginator.create(parseInt(jqXHR.getResponseHeader('total-entries')), perPage, 0, onPageSelected)
|
||||
$('#local-recordings-dialog .paginator-holder').append($paginator);
|
||||
});
|
||||
}
|
||||
|
||||
function afterHide() {
|
||||
showing = false;
|
||||
}
|
||||
|
||||
|
||||
function onPageSelected(targetPage) {
|
||||
return getRecordings(targetPage);
|
||||
}
|
||||
|
||||
function getRecordings(page) {
|
||||
return rest.getClaimedRecordings({page:page + 1, per_page:10})
|
||||
.done(function(claimedRecordings) {
|
||||
|
||||
emptyList();
|
||||
|
||||
var $tbody = tbody();
|
||||
|
||||
var recordings = $.map(claimedRecordings, function(val, i) { return val.recording; });
|
||||
var localResults = context.jamClient.GetLocalRecordingState({recordings: recordings});
|
||||
|
||||
if(localResults['error']) {
|
||||
app.notify({
|
||||
title : "Get Recording State Failure",
|
||||
text : localResults['error'],
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
app.layout.closeDialog('localRecordings');
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(claimedRecordings, function(index, claimedRecording) {
|
||||
|
||||
var options = {
|
||||
recordingId: claimedRecording.recording.id,
|
||||
//date: context.JK.formatDate(claimedRecording.recording.created_at),
|
||||
//time: context.JK.formatTime(claimedRecording.recording.created_at),
|
||||
timeago: $.timeago(claimedRecording.recording.created_at),
|
||||
name: claimedRecording.name,
|
||||
aggregate_state: localResults.recordings[index]['aggregate_state'],
|
||||
duration: context.JK.prettyPrintSeconds(claimedRecording.recording.duration)
|
||||
};
|
||||
|
||||
var tr = $(context._.template($('#template-claimed-recording-row').html(), options, { variable: 'data' }));
|
||||
|
||||
tr.data('server-model', claimedRecording);
|
||||
$tbody.append(tr);
|
||||
});
|
||||
})
|
||||
.fail(function(jqXHR, textStatus, errorMessage) {
|
||||
app.ajaxError(jqXHR, textStatus, errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
function registerStaticEvents() {
|
||||
$('#local-recordings-dialog table.local-recordings tbody').on('click', 'tr', function(e) {
|
||||
|
||||
var localState = $(this).attr('data-local-state');
|
||||
|
||||
if(localState == 'MISSING') {
|
||||
app.notify({
|
||||
title : "Can't Open Recording",
|
||||
text : "The recording is missing all tracks",
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
}
|
||||
else if(localState == 'PARTIALLY_MISSING') {
|
||||
app.notify({
|
||||
title : "Can't Open Recording",
|
||||
text : "The recording is missing some tracks",
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var claimedRecording = $(this).data('server-model');
|
||||
|
||||
// tell the server we are about to start a recording
|
||||
rest.startPlayClaimedRecording({id: context.JK.CurrentSessionModel.id(), claimed_recording_id: claimedRecording.id})
|
||||
.done(function(response) {
|
||||
var recordingId = $(this).attr('data-recording-id');
|
||||
var openRecordingResult = context.jamClient.OpenRecording(claimedRecording.recording);
|
||||
|
||||
logger.debug("OpenRecording response: %o", openRecordingResult);
|
||||
|
||||
if(openRecordingResult.error) {
|
||||
app.notify({
|
||||
"title": "Can't Open Recording",
|
||||
"text": openRecordingResult.error,
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
|
||||
rest.stopPlayClaimedRecording({id: context.JK.CurrentSessionModel.id(), claimed_recording_id: claimedRecording.id})
|
||||
.fail(function(jqXHR) {
|
||||
app.notify({
|
||||
"title": "Couldn't Stop Recording Playback",
|
||||
"text": "Couldn't inform the server to stop playback. msg=" + jqXHR.responseText,
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
})
|
||||
}
|
||||
else {
|
||||
app.layout.closeDialog('localRecordings');
|
||||
$(this).triggerHandler('openedSession', {});
|
||||
}
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
app.notifyServerError(jqXHR, "Unable to Open Recording For Playback");
|
||||
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
return false;
|
||||
})
|
||||
}
|
||||
|
||||
function initialize(){
|
||||
var dialogBindings = {
|
||||
'beforeShow' : beforeShow,
|
||||
'afterHide': afterHide
|
||||
};
|
||||
|
||||
app.bindDialog('localRecordings', dialogBindings);
|
||||
|
||||
registerStaticEvents();
|
||||
};
|
||||
|
||||
|
||||
this.initialize = initialize;
|
||||
this.isShowing = function isShowing() { return showing; }
|
||||
}
|
||||
|
||||
return this;
|
||||
})(window,jQuery);
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* Static functions for creating pagination
|
||||
*/
|
||||
(function(context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
|
||||
context.JK.Paginator = {
|
||||
|
||||
/** returns a jquery object that encapsulates pagination markup.
|
||||
* It's left to the caller to append it to the page as they like.
|
||||
* @param pages the number of pages
|
||||
* @param currentPage the current page
|
||||
* @param onPageSelected when a new page is selected. receives one argument; the page number.
|
||||
* the function should return a deferred object (whats returned by $.ajax), and that response has to have a 'total-entries' header set
|
||||
*/
|
||||
create:function(totalEntries, perPage, currentPage, onPageSelected) {
|
||||
|
||||
function calculatePages(total, perPageValue) {
|
||||
return Math.ceil(total / perPageValue);
|
||||
}
|
||||
|
||||
|
||||
function attemptToMoveToTargetPage(targetPage) {
|
||||
|
||||
// 'working' == click guard
|
||||
var working = paginator.data('working');
|
||||
if(!working) {
|
||||
paginator.data('working', true);
|
||||
|
||||
onPageSelected(targetPage)
|
||||
.done(function(data, textStatus, jqXHR) {
|
||||
totalEntries = parseInt(jqXHR.getResponseHeader('total-entries'));
|
||||
pages = calculatePages(totalEntries, perPage);
|
||||
options = { pages: pages,
|
||||
currentPage: targetPage };
|
||||
|
||||
// recreate the pagination, and
|
||||
var newPaginator = $(context._.template($('#template-paginator').html(), options, { variable: 'data' }));
|
||||
registerEvents(newPaginator);
|
||||
paginator.replaceWith(newPaginator);
|
||||
paginator = newPaginator;
|
||||
})
|
||||
.always(function() {
|
||||
paginator.data('working', false);
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log("workin fool: %o", working)
|
||||
}
|
||||
}
|
||||
|
||||
function registerEvents(paginator) {
|
||||
$('a.page-less', paginator).click(function(e) {
|
||||
var currentPage = parseInt($(this).attr('data-current-page'));
|
||||
if (currentPage > 0) {
|
||||
var targetPage = currentPage - 1;
|
||||
attemptToMoveToTargetPage(targetPage);
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$('a.page-more', paginator).click(function(e) {
|
||||
var currentPage = parseInt($(this).attr('data-current-page'));
|
||||
if (currentPage < pages - 1) {
|
||||
var targetPage = currentPage + 1;
|
||||
attemptToMoveToTargetPage(targetPage);
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$('a.page-link', paginator).click(function(e) {
|
||||
var targetPage = parseInt($(this).attr('data-page'));
|
||||
attemptToMoveToTargetPage(targetPage);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var pages = calculatePages(totalEntries, perPage);
|
||||
|
||||
var options = { pages: pages,
|
||||
currentPage: currentPage };
|
||||
|
||||
var paginator = $(context._.template($('#template-paginator').html(), options, { variable: 'data' }));
|
||||
|
||||
registerEvents(paginator);
|
||||
|
||||
return paginator;
|
||||
}
|
||||
}
|
||||
})(window, jQuery);
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
/**
|
||||
* Static functions for creating pagination
|
||||
*/
|
||||
(function(context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var PlaybackMode = {
|
||||
NoPlayback: 0,
|
||||
EveryWhere: 1,
|
||||
PrivatePreview: 2,
|
||||
PreviewToAll: 3,
|
||||
LastPbMode: 4
|
||||
};
|
||||
|
||||
|
||||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.PlaybackControls = function($parentElement, options){
|
||||
|
||||
options = $.extend(false, {playmodeControlsVisible:false}, options);
|
||||
|
||||
var logger = context.JK.logger;
|
||||
if($parentElement.length == 0) {
|
||||
logger.debug("no $parentElement specified in PlaybackControls");
|
||||
}
|
||||
|
||||
var $playButton = $('.play-button img.playbutton', $parentElement);
|
||||
var $pauseButton = $('.play-button img.pausebutton', $parentElement);
|
||||
var $currentTime = $('.recording-current', $parentElement);
|
||||
var $duration = $('.duration-time', $parentElement);
|
||||
var $sliderBar = $('.recording-playback', $parentElement);
|
||||
var $slider = $('.recording-slider', $parentElement);
|
||||
var $playmodeButton = $('.playback-mode-buttons.icheckbuttons input', $parentElement);
|
||||
|
||||
var $self = $(this);
|
||||
|
||||
var playbackPlaying = false;
|
||||
var playbackDurationMs = 0;
|
||||
var playbackPositionMs = 0;
|
||||
var durationChanged = false;
|
||||
|
||||
var endReached = false;
|
||||
var dragging = false;
|
||||
var playingWhenDragStart = false;
|
||||
var draggingUpdateTimer = null;
|
||||
var canUpdateBackend = false;
|
||||
var playbackMode = PlaybackMode.EveryWhere;
|
||||
var monitorPlaybackTimeout = null;
|
||||
|
||||
function startPlay() {
|
||||
updateIsPlaying(true);
|
||||
if(endReached) {
|
||||
update(0, playbackDurationMs, playbackPlaying);
|
||||
}
|
||||
$self.triggerHandler('play', {playbackMode: playbackMode});
|
||||
}
|
||||
|
||||
function stopPlay() {
|
||||
updateIsPlaying(false);
|
||||
$self.triggerHandler('pause');
|
||||
}
|
||||
|
||||
function updateOffsetBasedOnPosition(offsetLeft) {
|
||||
var sliderBarWidth = $sliderBar.width();
|
||||
|
||||
playbackPositionMs = parseInt((offsetLeft / sliderBarWidth) * playbackDurationMs);
|
||||
updateCurrentTimeText(playbackPositionMs);
|
||||
if(canUpdateBackend) {
|
||||
$self.triggerHandler('change-position', {positionMs: playbackPositionMs});
|
||||
canUpdateBackend = false;
|
||||
}
|
||||
}
|
||||
|
||||
function startDrag(e, ui) {
|
||||
dragging = true;
|
||||
playingWhenDragStart = playbackPlaying;
|
||||
draggingUpdateTimer = setInterval(function() { canUpdateBackend = true; }, 333); // only call backend up to 3 times a second while dragging
|
||||
if(playingWhenDragStart) {
|
||||
stopPlay();
|
||||
}
|
||||
}
|
||||
|
||||
function stopDrag(e, ui) {
|
||||
dragging = false;
|
||||
|
||||
clearInterval(draggingUpdateTimer);
|
||||
|
||||
canUpdateBackend = true;
|
||||
updateOffsetBasedOnPosition(ui.position.left);
|
||||
|
||||
if(playingWhenDragStart) {
|
||||
playingWhenDragStart = false;
|
||||
startPlay();
|
||||
}
|
||||
}
|
||||
|
||||
function onDrag(e, ui) {
|
||||
updateOffsetBasedOnPosition(ui.position.left);
|
||||
}
|
||||
|
||||
$playButton.on('click', function(e) {
|
||||
startPlay();
|
||||
return false;
|
||||
});
|
||||
|
||||
$pauseButton.on('click', function(e) {
|
||||
stopPlay();
|
||||
return false;
|
||||
});
|
||||
|
||||
$sliderBar.on('click', function(e) {
|
||||
var offset = e.pageX - $(this).offset().left;
|
||||
canUpdateBackend = true;
|
||||
updateOffsetBasedOnPosition(offset);
|
||||
updateSliderPosition(playbackPositionMs);
|
||||
return false;
|
||||
});
|
||||
|
||||
$slider.draggable({
|
||||
axis: 'x',
|
||||
containment: $sliderBar,
|
||||
start: startDrag,
|
||||
stop: stopDrag,
|
||||
drag: onDrag
|
||||
});
|
||||
|
||||
|
||||
if(options.playmodeControlsVisible) {
|
||||
$('.playback-mode-buttons.icheckbuttons', $parentElement).show();
|
||||
}
|
||||
|
||||
$playmodeButton.iCheck({
|
||||
checkboxClass: 'icheckbox_minimal',
|
||||
radioClass: 'iradio_minimal',
|
||||
inheritClass: true
|
||||
});
|
||||
|
||||
|
||||
$playmodeButton.on('ifChecked', function(e) {
|
||||
var playmode = $(this).val();
|
||||
console.log("set new playmode", playmode);
|
||||
setPlaybackMode(playmode);
|
||||
});
|
||||
|
||||
function monitorRecordingPlayback() {
|
||||
var isPlaying = context.jamClient.isSessionTrackPlaying();
|
||||
var positionMs = context.jamClient.SessionCurrrentPlayPosMs();
|
||||
var durationMs = context.jamClient.SessionGetTracksPlayDurationMs();
|
||||
|
||||
update(positionMs, durationMs, isPlaying);
|
||||
|
||||
monitorPlaybackTimeout = setTimeout(monitorRecordingPlayback, 500);
|
||||
}
|
||||
|
||||
function update(currentTimeMs, durationTimeMs, isPlaying) {
|
||||
|
||||
if(dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
// at the end of the play, the duration sets to 0, as does currentTime. but isPlaying does not reset to
|
||||
console.log("currentTimeMs, durationTimeMs", currentTimeMs, durationTimeMs);
|
||||
if(currentTimeMs == 0 && durationTimeMs == 0) {
|
||||
if(isPlaying) {
|
||||
isPlaying = false;
|
||||
durationTimeMs = playbackDurationMs;
|
||||
currentTimeMs = playbackDurationMs;
|
||||
stopPlay();
|
||||
endReached = true;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateDurationTime(durationTimeMs);
|
||||
updateCurrentTime(currentTimeMs);
|
||||
updateIsPlaying(isPlaying);
|
||||
|
||||
durationChanged = false;
|
||||
}
|
||||
|
||||
function updateDurationTime(timeMs) {
|
||||
if(timeMs != playbackDurationMs) {
|
||||
$duration.text(context.JK.prettyPrintSeconds(parseInt(timeMs / 1000)));
|
||||
playbackDurationMs = timeMs;
|
||||
durationChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCurrentTimeText(timeMs) {
|
||||
$currentTime.text(context.JK.prettyPrintSeconds(parseInt(timeMs / 1000)));
|
||||
}
|
||||
|
||||
function updateSliderPosition(timeMs) {
|
||||
|
||||
var slideWidthPx = $sliderBar.width();
|
||||
var xPos = Math.ceil(timeMs / playbackDurationMs * slideWidthPx);
|
||||
$slider.css('left', xPos);
|
||||
}
|
||||
|
||||
function updateCurrentTime(timeMs) {
|
||||
if(timeMs != playbackPositionMs || durationChanged) {
|
||||
|
||||
updateCurrentTimeText(timeMs);
|
||||
updateSliderPosition(timeMs);
|
||||
|
||||
playbackPositionMs = timeMs;
|
||||
}
|
||||
}
|
||||
|
||||
function updateIsPlaying(isPlaying) {
|
||||
if(isPlaying != playbackPlaying) {
|
||||
if(isPlaying) {
|
||||
$playButton.hide();
|
||||
$pauseButton.show();
|
||||
}
|
||||
else {
|
||||
$playButton.show();
|
||||
$pauseButton.hide();
|
||||
}
|
||||
|
||||
playbackPlaying = isPlaying;
|
||||
}
|
||||
}
|
||||
|
||||
function setPlaybackMode(mode) {
|
||||
if(mode == 'preview-to-all') {
|
||||
playbackMode = PlaybackMode.PreviewToAll;
|
||||
}
|
||||
else if(mode == 'preview-to-me') {
|
||||
playbackMode = PlaybackMode.PrivatePreview;
|
||||
}
|
||||
else if(mode == 'eveywhere') {
|
||||
playbackMode = PlaybackMode.EveryWhere;
|
||||
}
|
||||
else {
|
||||
logger.error("unable to set playback mode", mode);
|
||||
}
|
||||
|
||||
// let the mode change immediately affect the behavior of the stream
|
||||
if(playbackPlaying) {
|
||||
stopPlay();
|
||||
startPlay();
|
||||
}
|
||||
}
|
||||
|
||||
function startMonitor() {
|
||||
monitorRecordingPlayback();
|
||||
}
|
||||
|
||||
function stopMonitor() {
|
||||
if(monitorPlaybackTimeout!= null) {
|
||||
clearTimeout(monitorPlaybackTimeout);
|
||||
monitorPlaybackTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.update = update;
|
||||
this.setPlaybackMode = setPlaybackMode;
|
||||
this.startMonitor = startMonitor;
|
||||
this.stopMonitor = stopMonitor;
|
||||
|
||||
return this;
|
||||
}
|
||||
})(window, jQuery);
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
var logger = context.JK.logger;
|
||||
var userId;
|
||||
var user = null;
|
||||
var rest = context.JK.Rest();
|
||||
|
||||
var instrument_logo_map = context.JK.getInstrumentIconMap24();
|
||||
|
||||
|
|
@ -24,13 +25,12 @@
|
|||
|
||||
function beforeShow(data) {
|
||||
userId = data.id;
|
||||
user = null;
|
||||
user = null;
|
||||
}
|
||||
|
||||
function afterShow(data) {
|
||||
initUser();
|
||||
resetForm();
|
||||
events();
|
||||
renderActive();
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
|
|
@ -46,83 +46,76 @@
|
|||
$('.profile-nav a.#profile-about-link').addClass('active');
|
||||
}
|
||||
|
||||
function getUser() {
|
||||
if (user === null) {
|
||||
var url = "/api/users/" + userId;
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: url,
|
||||
async: false,
|
||||
processData:false,
|
||||
success: function(response) {
|
||||
user = response;
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorMessage) {
|
||||
user = null;
|
||||
app.ajaxError(jqXHR, textStatus, errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
return user;
|
||||
}
|
||||
function initUser() {
|
||||
if (user === null) {
|
||||
rest.getUserDetail({"id": userId})
|
||||
.done(function(response) {
|
||||
user = response;
|
||||
events();
|
||||
renderActive();
|
||||
})
|
||||
.fail(app.ajaxError);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
function isMusician() {
|
||||
if (getUser()) {
|
||||
return user.musician === true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isMusician() {
|
||||
if (user) {
|
||||
return user.musician === true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isCurrentUser() {
|
||||
return userId === context.JK.currentUserId;
|
||||
}
|
||||
function isCurrentUser() {
|
||||
return userId === context.JK.currentUserId;
|
||||
}
|
||||
|
||||
function configureUserType() {
|
||||
if (isMusician()) {
|
||||
$('#profile-history-link').show();
|
||||
$('#profile-bands-link').show();
|
||||
$('#profile-instruments').show();
|
||||
$('#profile-session-stats').show();
|
||||
$('#profile-recording-stats').show();
|
||||
function configureUserType() {
|
||||
if (isMusician()) {
|
||||
$('#profile-history-link').show();
|
||||
$('#profile-bands-link').show();
|
||||
$('#profile-instruments').show();
|
||||
$('#profile-session-stats').show();
|
||||
$('#profile-recording-stats').show();
|
||||
|
||||
// $('#profile-following-stats').hide();
|
||||
// $('#profile-favorites-stats').hide();
|
||||
// $('#profile-following-stats').hide();
|
||||
// $('#profile-favorites-stats').hide();
|
||||
|
||||
$('#btn-add-friend').show();
|
||||
$('#btn-add-friend').show();
|
||||
$('.profile-social-left').show();
|
||||
|
||||
$('#profile-type-label').text('musician');
|
||||
$('#profile-location-label').text('Location');
|
||||
$('#profile-type-label').text('musician');
|
||||
$('#profile-location-label').text('Location');
|
||||
}
|
||||
else {
|
||||
$('#profile-history-link').hide();
|
||||
$('#profile-bands-link').hide();
|
||||
$('#profile-instruments').hide();
|
||||
$('#profile-session-stats').hide();
|
||||
$('#profile-recording-stats').hide();
|
||||
|
||||
} else {
|
||||
$('#profile-history-link').hide();
|
||||
$('#profile-bands-link').hide();
|
||||
$('#profile-instruments').hide();
|
||||
$('#profile-session-stats').hide();
|
||||
$('#profile-recording-stats').hide();
|
||||
|
||||
// $('#profile-following-stats').show();
|
||||
// $('#profile-favorites-stats').show();
|
||||
|
||||
$('#btn-add-friend').hide();
|
||||
// $('#profile-following-stats').show();
|
||||
// $('#profile-favorites-stats').show();
|
||||
|
||||
$('#btn-add-friend').hide();
|
||||
$('.profile-social-left').hide();
|
||||
|
||||
$('#profile-type-label').text('fan');
|
||||
$('#profile-location-label').text('Presence');
|
||||
}
|
||||
$('#profile-type-label').text('fan');
|
||||
$('#profile-location-label').text('Presence');
|
||||
}
|
||||
|
||||
if (isCurrentUser()) {
|
||||
if (isCurrentUser()) {
|
||||
$('#btn-profile-edit').show();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$('#btn-profile-edit').hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************** MAIN PORTION OF SCREEN *****************/
|
||||
// events for main screen
|
||||
function events() {
|
||||
configureUserType();
|
||||
configureUserType();
|
||||
|
||||
// wire up panel clicks
|
||||
$('#profile-about-link').click(renderAbout);
|
||||
|
|
@ -168,7 +161,7 @@
|
|||
}
|
||||
|
||||
function isFriend() {
|
||||
return getUser() ? user.is_friend : false;
|
||||
return user ? user.is_friend : false;
|
||||
}
|
||||
|
||||
function friendRequestCallback() {
|
||||
|
|
@ -240,7 +233,7 @@
|
|||
}
|
||||
|
||||
function isFollowing() {
|
||||
return getUser() ? user.is_following : false;
|
||||
return user ? user.is_following : false;
|
||||
}
|
||||
|
||||
function configureFollowingButton(following) {
|
||||
|
|
@ -300,7 +293,7 @@
|
|||
function bindAbout() {
|
||||
$('#profile-instruments').empty();
|
||||
|
||||
if (getUser()) {
|
||||
if (user !== null) {
|
||||
// name
|
||||
$('#profile-username').html(user.name);
|
||||
|
||||
|
|
@ -338,18 +331,18 @@
|
|||
text = user.follower_count > 1 || user.follower_count === 0 ? " Followers" : " Follower";
|
||||
$('#profile-follower-stats').html(user.follower_count + text);
|
||||
|
||||
if (isMusician()) {
|
||||
if (isMusician()) {
|
||||
text = user.session_count > 1 || user.session_count === 0 ? " Sessions" : " Session";
|
||||
$('#profile-session-stats').html(user.session_count + text);
|
||||
|
||||
text = user.recording_count > 1 || user.recording_count === 0 ? " Recordings" : " Recording";
|
||||
$('#profile-recording-stats').html(user.recording_count + text);
|
||||
} else {
|
||||
} else {
|
||||
text = " Following";
|
||||
$('#profile-following-stats').html(user.following_count + text);
|
||||
text = user.favorite_count > 1 || user.favorite_count === 0 ? " Favorites" : " Favorite";
|
||||
$('#profile-favorite-stats').html(user.favorite_count + text);
|
||||
}
|
||||
}
|
||||
|
||||
$('#profile-biography').html(user.biography);
|
||||
}
|
||||
|
|
@ -373,41 +366,41 @@
|
|||
$('.profile-nav a.active').removeClass('active');
|
||||
$('.profile-nav a.#profile-social-link').addClass('active');
|
||||
|
||||
/*if (isMusician()) {
|
||||
/*if (isMusician()) {
|
||||
$('.profile-social-left').show();
|
||||
} else {
|
||||
} else {
|
||||
$('.profile-social-left').hide();
|
||||
}*/
|
||||
}*/
|
||||
|
||||
bindSocial();
|
||||
}
|
||||
|
||||
function bindSocial() {
|
||||
if (isMusician()) {
|
||||
// FRIENDS
|
||||
var url = "/api/users/" + userId + "/friends";
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: url,
|
||||
async: false,
|
||||
processData:false,
|
||||
success: function(response) {
|
||||
$.each(response, function(index, val) {
|
||||
var template = $('#template-profile-social').html();
|
||||
var friendHtml = context.JK.fillTemplate(template, {
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
userName: val.name,
|
||||
location: val.location,
|
||||
type: "Friends"
|
||||
});
|
||||
if (isMusician()) {
|
||||
// FRIENDS
|
||||
var url = "/api/users/" + userId + "/friends";
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: url,
|
||||
async: false,
|
||||
processData:false,
|
||||
success: function(response) {
|
||||
$.each(response, function(index, val) {
|
||||
var template = $('#template-profile-social').html();
|
||||
var friendHtml = context.JK.fillTemplate(template, {
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
userName: val.name,
|
||||
location: val.location,
|
||||
type: "Friends"
|
||||
});
|
||||
|
||||
$('#profile-social-friends').append(friendHtml);
|
||||
});
|
||||
},
|
||||
error: app.ajaxError
|
||||
});
|
||||
}
|
||||
$('#profile-social-friends').append(friendHtml);
|
||||
});
|
||||
},
|
||||
error: app.ajaxError
|
||||
});
|
||||
}
|
||||
|
||||
// FOLLOWINGS (USERS)
|
||||
url = "/api/users/" + userId + "/followings";
|
||||
|
|
@ -614,6 +607,7 @@
|
|||
|
||||
var newFollowing = {};
|
||||
newFollowing.band_id = bandId;
|
||||
logger.debug("Following band " + bandId);
|
||||
|
||||
var url = "/api/users/" + context.JK.currentUserId + "/followings";
|
||||
$.ajax({
|
||||
|
|
@ -624,6 +618,7 @@
|
|||
data: JSON.stringify(newFollowing),
|
||||
processData: false,
|
||||
success: function(response) {
|
||||
logger.debug("following band " + bandId);
|
||||
renderBands(); // refresh stats
|
||||
configureBandFollowingButton(true, bandId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,240 @@
|
|||
(function(context,$) {
|
||||
|
||||
"use strict";
|
||||
context.JK = context.JK || {};
|
||||
context.JK.RecordingFinishedDialog = function(app) {
|
||||
var logger = context.JK.logger;
|
||||
var rest = context.JK.Rest();
|
||||
var playbackControls = null;
|
||||
var recording = null; // deferred object
|
||||
|
||||
function resetForm() {
|
||||
|
||||
// remove all display errors
|
||||
$('#recording-finished-dialog form .error-text').remove()
|
||||
$('#recording-finished-dialog form .error').removeClass("error")
|
||||
}
|
||||
|
||||
function beforeShow() {
|
||||
if(recording == null) {
|
||||
alert("recording data should not be null");
|
||||
app.layout.closeDialog('recordingFinished');
|
||||
return false;
|
||||
}
|
||||
|
||||
resetForm();
|
||||
|
||||
var parentSelector = '#recording-finished-dialog div.genre-selector';
|
||||
context.JK.GenreSelectorHelper.render(parentSelector);
|
||||
|
||||
// preset genre from 1st genre in current session
|
||||
var currentOrLastSession = JK.CurrentSessionModel.getCurrentOrLastSession();
|
||||
if(currentOrLastSession && currentOrLastSession.genres.length > 0) {
|
||||
var genreDescription = currentOrLastSession.genres[0];
|
||||
context.JK.GenreSelectorHelper.setSelectedGenres(parentSelector, [genreDescription]);
|
||||
}
|
||||
|
||||
var localResults = context.jamClient.GetLocalRecordingState({recordings: [recording]});
|
||||
|
||||
|
||||
if(localResults['error']) {
|
||||
app.notify({
|
||||
title : "Unable to Open Recording for Playback",
|
||||
text : localResults['error'],
|
||||
icon_url: "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
}
|
||||
else {
|
||||
var localResult = localResults.recordings[0];
|
||||
if(localResult.aggregate_state == 'MISSING') {
|
||||
app.notify({
|
||||
title : "Unable to Open Recording for Playback",
|
||||
text : "All tracks associated with the recording are missing",
|
||||
icon_url: "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
}
|
||||
else if(localResult.aggregate_state == 'PARTIALLY_MISSING') {
|
||||
app.notify({
|
||||
title : "Unable to Open Recording for Playback",
|
||||
text: "Some tracks associated with the recording are missing",
|
||||
icon_url: "/assets/content/icon_alert_big.png"
|
||||
})
|
||||
}
|
||||
else {
|
||||
|
||||
// load recording
|
||||
var openRecordingResult = context.jamClient.OpenRecording(recording);
|
||||
|
||||
logger.debug("OpenRecording response: %o", openRecordingResult);
|
||||
|
||||
if(openRecordingResult.error) {
|
||||
app.notify({
|
||||
"title": "Can't Open Recording",
|
||||
"text": openRecordingResult.error,
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
}
|
||||
|
||||
playbackControls.startMonitor();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function afterHide() {
|
||||
recording = null;
|
||||
playbackControls.stopMonitor();
|
||||
context.jamClient.CloseRecording();
|
||||
}
|
||||
|
||||
function discardRecording(e) {
|
||||
|
||||
resetForm();
|
||||
registerDiscardRecordingHandlers(false);
|
||||
|
||||
rest.discardRecording({
|
||||
id: recording.id
|
||||
})
|
||||
.done(function() {
|
||||
console.error("recording discarded by user. recordingId=%o", recording.id);
|
||||
})
|
||||
.fail(function(jqXHR){
|
||||
console.error("recording discard by user failed. recordingId=%o. reason: %o", recording.id, jqXHR.responseText);
|
||||
})
|
||||
.always(function() {
|
||||
app.layout.closeDialog('recordingFinished')
|
||||
registerDiscardRecordingHandlers(true);
|
||||
})
|
||||
return false;
|
||||
}
|
||||
function claimRecording(e){
|
||||
|
||||
resetForm();
|
||||
registerClaimRecordingHandlers(false);
|
||||
|
||||
var name = $('#recording-finished-dialog form input[name=name]').val();
|
||||
var description = $('#recording-finished-dialog form textarea[name=description]').val();
|
||||
var genre = $('#recording-finished-dialog form select[name=genre]').val();
|
||||
var is_public = $('#recording-finished-dialog form input[name=is_public]').is(':checked')
|
||||
var is_downloadable = $('#recording-finished-dialog form input[name=is_downloadable]').is(':checked');
|
||||
|
||||
rest.claimRecording({
|
||||
id : recording.id,
|
||||
name: name,
|
||||
description: description,
|
||||
genre: genre,
|
||||
is_public: is_public,
|
||||
is_downloadable: is_downloadable
|
||||
})
|
||||
.done(function() {
|
||||
app.layout.closeDialog('recordingFinished')
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
if(jqXHR.status == 422) {
|
||||
var errors = JSON.parse(jqXHR.responseText);
|
||||
|
||||
var $name_errors = context.JK.format_errors('name', errors);
|
||||
if($name_errors) $('#recording-finished-dialog form input[name=name]').closest('div.field').addClass('error').end().after($name_errors);
|
||||
|
||||
var $description_errors = context.JK.format_errors('description', errors);
|
||||
if($description_errors) $('#recording-finished-dialog form input[name=description]').closest('div.field').addClass('error').end().after($description_errors);
|
||||
|
||||
var $genre_errors = context.JK.format_errors('genre', errors);
|
||||
if($genre_errors) $('#recording-finished-dialog form select[name=genre]').closest('div.field').addClass('error').end().after($genre_errors);
|
||||
|
||||
var $is_public_errors = context.JK.format_errors('is_public', errors);
|
||||
if($is_public_errors) $('#recording-finished-dialog form input[name=is_public]').closest('div.field').addClass('error').end().after($is_public_errors);
|
||||
|
||||
var $is_downloadable_errors = context.JK.format_errors('is_downloadable', errors);
|
||||
if($is_downloadable_errors) $('#recording-finished-dialog form input[name=is_downloadable]').closest('div.field').addClass('error').end().after($is_downloadable_errors);
|
||||
|
||||
var recording_error = context.JK.get_first_error('recording_id', errors);
|
||||
|
||||
if (recording_error) context.JK.showErrorDialog(app, "Unable to claim recording.", recording_error);
|
||||
}
|
||||
else {
|
||||
logger.error("unable to claim recording %o", arguments);
|
||||
|
||||
context.JK.showErrorDialog(app, "Unable to claim recording.", jqXHR.responseText);
|
||||
}
|
||||
})
|
||||
.always(function() {
|
||||
registerClaimRecordingHandlers(true);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
function registerClaimRecordingHandlers(onOff) {
|
||||
if(onOff) {
|
||||
$('#keep-session-recording').on('click', claimRecording);
|
||||
$('#recording-finished-dialog form').on('submit', claimRecording);
|
||||
}
|
||||
else {
|
||||
$('#keep-session-recording').off('click', claimRecording)
|
||||
$('#recording-finished-dialog form').off('submit', claimRecording);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function registerDiscardRecordingHandlers(onOff) {
|
||||
if(onOff) {
|
||||
$('#discard-session-recording').on('click', discardRecording);
|
||||
}
|
||||
else {
|
||||
$('#discard-session-recording').off('click', discardRecording);
|
||||
}
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
logger.debug("calling jamClient.SessionStopPlay");
|
||||
context.jamClient.SessionStopPlay();
|
||||
}
|
||||
|
||||
function onPlay(e, data) {
|
||||
logger.debug("calling jamClient.SessionStartPlay");
|
||||
context.jamClient.SessionStartPlay(data.playbackMode);
|
||||
}
|
||||
|
||||
function onChangePlayPosition(e, data) {
|
||||
logger.debug("calling jamClient.SessionTrackSeekMs(" + data.positionMs + ")");
|
||||
context.jamClient.SessionTrackSeekMs(data.positionMs);
|
||||
}
|
||||
|
||||
function registerStaticEvents() {
|
||||
registerClaimRecordingHandlers(true);
|
||||
registerDiscardRecordingHandlers(true);
|
||||
$(playbackControls)
|
||||
.on('pause', onPause)
|
||||
.on('play', onPlay)
|
||||
.on('change-position', onChangePlayPosition);
|
||||
}
|
||||
|
||||
function setRecording(recordingData) {
|
||||
if(recording != null) {
|
||||
//XXX - prevent start/stop recording mashing; protect this dialog
|
||||
logger.error("unable to set recording data over existing recording data. this coudld be due to start/stop recording mashing");
|
||||
return;
|
||||
}
|
||||
recording = recordingData;
|
||||
}
|
||||
|
||||
function initialize(){
|
||||
var dialogBindings = {
|
||||
'beforeShow' : beforeShow,
|
||||
'afterHide': afterHide
|
||||
};
|
||||
|
||||
app.bindDialog('recordingFinished', dialogBindings);
|
||||
|
||||
playbackControls = new context.JK.PlaybackControls($('#recording-finished-dialog .recording-controls'));
|
||||
|
||||
registerStaticEvents();
|
||||
};
|
||||
|
||||
|
||||
this.initialize = initialize;
|
||||
this.setRecording = setRecording;
|
||||
}
|
||||
|
||||
return this;
|
||||
})(window,jQuery);
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
context.JK.RecordingModel = function(app, sessionModel, _rest, _jamClient) {
|
||||
var currentRecording = null; // the JSON response from the server for a recording
|
||||
var currentOrLastRecordingId = null;
|
||||
var currentRecordingId = null;
|
||||
var rest = _rest;
|
||||
var currentlyRecording = false;
|
||||
|
|
@ -57,6 +58,7 @@
|
|||
currentRecordingId = null;
|
||||
}
|
||||
|
||||
|
||||
function groupTracksToClient(recording) {
|
||||
// group N tracks to the same client Id
|
||||
var groupedTracks = {};
|
||||
|
|
@ -83,12 +85,13 @@
|
|||
currentRecording = rest.startRecording({"music_session_id": sessionModel.id()})
|
||||
.done(function(recording) {
|
||||
currentRecordingId = recording.id;
|
||||
currentOrLastRecordingId = recording.id;
|
||||
|
||||
// ask the backend to start the session.
|
||||
var groupedTracks = groupTracksToClient(recording);
|
||||
jamClient.StartRecording(recording["id"], groupedTracks);
|
||||
})
|
||||
.fail(function() {
|
||||
.fail(function(jqXHR) {
|
||||
$self.triggerHandler('startedRecording', { clientId: app.clientId, reason: 'rest', detail: arguments });
|
||||
currentlyRecording = false;
|
||||
})
|
||||
|
|
@ -220,6 +223,7 @@
|
|||
})
|
||||
.done(function(recording) {
|
||||
currentRecordingId = recording.id;
|
||||
currentOrLastRecordingId = recording.id;
|
||||
});
|
||||
|
||||
$self.triggerHandler('startingRecording', {recordingId: recordingId});
|
||||
|
|
@ -320,6 +324,7 @@
|
|||
this.isRecording = isRecording;
|
||||
this.reset = reset;
|
||||
this.stopRecordingIfNeeded = stopRecordingIfNeeded;
|
||||
this.currentOrLastRecordingId = function () { return currentOrLastRecordingId; };
|
||||
|
||||
context.JK.HandleRecordingStartResult = handleRecordingStartResult;
|
||||
context.JK.HandleRecordingStopResult = handleRecordingStopResult;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
var mixers = [];
|
||||
var configureTrackDialog;
|
||||
var addNewGearDialog;
|
||||
var localRecordingsDialog = null;
|
||||
var recordingFinishedDialog = null;
|
||||
var screenActive = false;
|
||||
var currentMixerRangeMin = null;
|
||||
var currentMixerRangeMax = null;
|
||||
|
|
@ -22,6 +24,8 @@
|
|||
var recordingTimerInterval = null;
|
||||
var startTimeDate = null;
|
||||
var startingRecording = false; // double-click guard
|
||||
var claimedRecording = null;
|
||||
var playbackControls = null;
|
||||
|
||||
|
||||
var rest = JK.Rest();
|
||||
|
|
@ -242,6 +246,10 @@
|
|||
else if(data.reason == 'recording-engine-sample-rate') {
|
||||
notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail);
|
||||
}
|
||||
else if(data.reason == 'rest') {
|
||||
var jqXHR = detail[0];
|
||||
app.notifyServerError(jqXHR);
|
||||
}
|
||||
else {
|
||||
notifyWithUserInfo(title, 'Error Reason: ' + reason);
|
||||
}
|
||||
|
|
@ -356,8 +364,26 @@
|
|||
.fail(app.ajaxError);
|
||||
}
|
||||
|
||||
function handleTransitionsInRecordingPlayback() {
|
||||
// let's see if we detect a transition to start playback or stop playback
|
||||
|
||||
var currentSession = sessionModel.getCurrentSession();
|
||||
|
||||
if(claimedRecording == null && (currentSession && currentSession.claimed_recording != null)) {
|
||||
// this is a 'started with a claimed_recording' transition.
|
||||
// we need to start a timer to watch for the state of the play session
|
||||
playbackControls.startMonitor();
|
||||
}
|
||||
else if(claimedRecording && (currentSession == null || currentSession.claimed_recording == null)) {
|
||||
playbackControls.stopMonitor();
|
||||
}
|
||||
|
||||
claimedRecording = currentSession == null ? null : currentSession.claimed_recording;
|
||||
|
||||
}
|
||||
function sessionChanged() {
|
||||
|
||||
handleTransitionsInRecordingPlayback();
|
||||
// TODO - in the specific case of a user changing their tracks using the configureTrack dialog,
|
||||
// this event appears to fire before the underlying mixers have updated. I have no event to
|
||||
// know definitively when the underlying mixers are up to date, so for now, we just delay slightly.
|
||||
|
|
@ -387,6 +413,7 @@
|
|||
$voiceChat.hide();
|
||||
_updateMixers();
|
||||
_renderTracks();
|
||||
_renderLocalMediaTracks();
|
||||
_wireTopVolume();
|
||||
_wireTopMix();
|
||||
_addVoiceChat();
|
||||
|
|
@ -394,6 +421,11 @@
|
|||
if ($('.session-livetracks .track').length === 0) {
|
||||
$('.session-livetracks .when-empty').show();
|
||||
}
|
||||
if ($('.session-recordings .track').length === 0) {
|
||||
$('.session-recordings .when-empty').show();
|
||||
$('.session-recording-name-wrapper').hide();
|
||||
$('.session-recordings .recording-controls').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function _initDialogs() {
|
||||
|
|
@ -406,6 +438,7 @@
|
|||
var mixerIds = context.jamClient.SessionGetIDs();
|
||||
var holder = $.extend(true, {}, {mixers: context.jamClient.SessionGetControlState(mixerIds)});
|
||||
mixers = holder.mixers;
|
||||
|
||||
// Always add a hard-coded simplified 'mixer' for the L2M mix
|
||||
var l2m_mixer = {
|
||||
id: '__L2M__',
|
||||
|
|
@ -416,6 +449,17 @@
|
|||
mixers.push(l2m_mixer);
|
||||
}
|
||||
|
||||
function _mixersForGroupId(groupId) {
|
||||
var foundMixers = [];
|
||||
$.each(mixers, function(index, mixer) {
|
||||
if (mixer.group_id === groupId) {
|
||||
foundMixers.push(mixer);
|
||||
}
|
||||
|
||||
});
|
||||
return foundMixers;
|
||||
}
|
||||
|
||||
// TODO FIXME - This needs to support multiple tracks for an individual
|
||||
// client id and group.
|
||||
function _mixerForClientId(clientId, groupIds, usedMixers) {
|
||||
|
|
@ -538,6 +582,113 @@
|
|||
});
|
||||
}
|
||||
|
||||
function _renderLocalMediaTracks() {
|
||||
var localMediaMixers = _mixersForGroupId(ChannelGroupIds.MediaTrackGroup);
|
||||
if(localMediaMixers.length == 0) {
|
||||
localMediaMixers = _mixersForGroupId(ChannelGroupIds.PeerMediaTrackGroup);
|
||||
}
|
||||
|
||||
var recordedTracks = sessionModel.recordedTracks();
|
||||
|
||||
console.log("recorded tracks=%o local_media_mixers=%o", recordedTracks, localMediaMixers);
|
||||
|
||||
if(recordedTracks && localMediaMixers.length == 0) {
|
||||
// if we are the creator, then rather than raise an error, tell the server the recording is over.
|
||||
// this shoudl only happen if we get temporarily disconnected by forced reload, which isn't a very normal scenario
|
||||
if(sessionModel.getCurrentSession().claimed_recording_initiator_id == context.JK.userMe.id) {
|
||||
closeRecording();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(recordedTracks) {
|
||||
|
||||
$('.session-recording-name').text(sessionModel.getCurrentSession().claimed_recording.name);
|
||||
|
||||
var noCorrespondingTracks = false;
|
||||
$.each(localMediaMixers, function(index, mixer) {
|
||||
var preMasteredClass = "";
|
||||
// find the track or tracks that correspond to the mixer
|
||||
var correspondingTracks = []
|
||||
$.each(recordedTracks, function(i, recordedTrack) {
|
||||
if(mixer.id.indexOf("L") == 0) {
|
||||
if(mixer.id.substring(1) == recordedTrack.client_track_id) {
|
||||
correspondingTracks.push(recordedTrack);
|
||||
}
|
||||
}
|
||||
else if(mixer.id.indexOf("C") == 0) {
|
||||
if(mixer.id.substring(1) == recordedTrack.client_id) {
|
||||
correspondingTracks.push(recordedTrack);
|
||||
preMasteredClass = "pre-mastered-track";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// this should not be possible
|
||||
alert("Invalid state: the recorded track had neither persisted_track_id or persisted_client_id");
|
||||
}
|
||||
});
|
||||
|
||||
if(correspondingTracks.length == 0) {
|
||||
noCorrespondingTracks = true;
|
||||
app.notify({
|
||||
title: "Unable to Open Recording",
|
||||
text: "Could not correlate server and client tracks",
|
||||
icon_url: "/assets/content/icon_alert_big.png"});
|
||||
return false;
|
||||
}
|
||||
|
||||
// prune found recorded tracks
|
||||
recordedTracks = $.grep(recordedTracks, function(value) {
|
||||
return $.inArray(value, correspondingTracks) < 0;
|
||||
});
|
||||
|
||||
var oneOfTheTracks = correspondingTracks[0];
|
||||
var instrumentIcon = context.JK.getInstrumentIcon45(oneOfTheTracks.instrument_id);
|
||||
var photoUrl = "/assets/content/icon_recording.png";
|
||||
|
||||
var name = oneOfTheTracks.user.name;
|
||||
if (!(name)) {
|
||||
name = oneOfTheTracks.user.first_name + ' ' + oneOfTheTracks.user.last_name;
|
||||
}
|
||||
|
||||
|
||||
// Default trackData to participant + no Mixer state.
|
||||
var trackData = {
|
||||
trackId: oneOfTheTracks.id,
|
||||
clientId: oneOfTheTracks.client_id,
|
||||
name: name,
|
||||
instrumentIcon: instrumentIcon,
|
||||
avatar: photoUrl,
|
||||
latency: "good",
|
||||
gainPercent: 0,
|
||||
muteClass: 'muted',
|
||||
mixerId: "",
|
||||
avatarClass : 'avatar-recording',
|
||||
preMasteredClass: preMasteredClass
|
||||
};
|
||||
|
||||
var gainPercent = percentFromMixerValue(
|
||||
mixer.range_low, mixer.range_high, mixer.volume_left);
|
||||
var muteClass = "enabled";
|
||||
if (mixer.mute) {
|
||||
muteClass = "muted";
|
||||
}
|
||||
trackData.gainPercent = gainPercent;
|
||||
trackData.muteClass = muteClass;
|
||||
trackData.mixerId = mixer.id;
|
||||
|
||||
_addMediaTrack(index, trackData);
|
||||
});
|
||||
|
||||
if(!noCorrespondingTracks && recordedTracks.length > 0) {
|
||||
logger.error("unable to find all recorded tracks against client tracks");
|
||||
app.notify({title:"All tracks not found",
|
||||
text: "Some tracks in the recording are not present in the playback",
|
||||
icon_url: "/assets/content/icon_alert_big.png"})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _renderTracks() {
|
||||
myTracks = [];
|
||||
|
||||
|
|
@ -572,7 +723,9 @@
|
|||
latency: "good",
|
||||
gainPercent: 0,
|
||||
muteClass: 'muted',
|
||||
mixerId: ""
|
||||
mixerId: "",
|
||||
avatarClass: 'avatar-med',
|
||||
preMasteredClass: ""
|
||||
};
|
||||
|
||||
// This is the likely cause of multi-track problems.
|
||||
|
|
@ -728,7 +881,7 @@
|
|||
$('.session-livetracks .when-empty').hide();
|
||||
}
|
||||
var template = $('#template-session-track').html();
|
||||
var newTrack = context.JK.fillTemplate(template, trackData);
|
||||
var newTrack = $(context.JK.fillTemplate(template, trackData));
|
||||
$destination.append(newTrack);
|
||||
|
||||
// Render VU meters and gain fader
|
||||
|
|
@ -747,6 +900,31 @@
|
|||
tracks[trackData.trackId] = new context.JK.SessionTrack(trackData.clientId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function _addMediaTrack(index, trackData) {
|
||||
var parentSelector = '#session-recordedtracks-container';
|
||||
var $destination = $(parentSelector);
|
||||
$('.session-recordings .when-empty').hide();
|
||||
$('.session-recording-name-wrapper').show();
|
||||
$('.session-recordings .recording-controls').show();
|
||||
|
||||
var template = $('#template-session-track').html();
|
||||
var newTrack = $(context.JK.fillTemplate(template, trackData));
|
||||
$destination.append(newTrack);
|
||||
if(trackData.preMasteredClass) {
|
||||
context.JK.helpBubble($('.track-instrument', newTrack), 'pre-processed-track', {}, {offsetParent: newTrack.closest('.content-body')});
|
||||
}
|
||||
|
||||
// Render VU meters and gain fader
|
||||
var trackSelector = parentSelector + ' .session-track[track-id="' + trackData.trackId + '"]';
|
||||
var gainPercent = trackData.gainPercent || 0;
|
||||
connectTrackToMixer(trackSelector, trackData.clientId, trackData.mixerId, gainPercent);
|
||||
|
||||
tracks[trackData.trackId] = new context.JK.SessionTrack(trackData.clientId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will be called when fader changes. The fader id (provided at subscribe time),
|
||||
* the new value (0-100) and whether the fader is still being dragged are passed.
|
||||
|
|
@ -1058,11 +1236,63 @@
|
|||
function promptUserToSave(recordingId) {
|
||||
rest.getRecording( {id: recordingId} )
|
||||
.done(function(recording) {
|
||||
recordingFinishedDialog.setRecording(recording);
|
||||
app.layout.showDialog('recordingFinished');
|
||||
})
|
||||
.fail(app.ajaxError);
|
||||
}
|
||||
|
||||
function openRecording(e) {
|
||||
// just ignore the click if they are currently recording for now
|
||||
if(sessionModel.recordingModel.isRecording()) {
|
||||
app.notify({
|
||||
"title": "Currently Recording",
|
||||
"text": "You can't open a recording while creating a recording.",
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!localRecordingsDialog.isShowing()) {
|
||||
app.layout.showDialog('localRecordings');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function closeRecording() {
|
||||
rest.stopPlayClaimedRecording({id: sessionModel.id(), claimed_recording_id: sessionModel.getCurrentSession().claimed_recording.id})
|
||||
.done(function() {
|
||||
sessionModel.refreshCurrentSession();
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
app.notify({
|
||||
"title": "Couldn't Stop Recording Playback",
|
||||
"text": "Couldn't inform the server to stop playback. msg=" + jqXHR.responseText,
|
||||
"icon_url": "/assets/content/icon_alert_big.png"
|
||||
});
|
||||
});
|
||||
|
||||
context.jamClient.CloseRecording();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
logger.debug("calling jamClient.SessionStopPlay");
|
||||
context.jamClient.SessionStopPlay();
|
||||
}
|
||||
|
||||
function onPlay(e, data) {
|
||||
logger.debug("calling jamClient.SessionStartPlay");
|
||||
context.jamClient.SessionStartPlay(data.playbackMode);
|
||||
}
|
||||
|
||||
function onChangePlayPosition(e, data){
|
||||
logger.debug("calling jamClient.SessionTrackSeekMs(" + data.positionMs + ")");
|
||||
context.jamClient.SessionTrackSeekMs(data.positionMs);
|
||||
}
|
||||
|
||||
function startStopRecording() {
|
||||
if(sessionModel.recordingModel.isRecording()) {
|
||||
sessionModel.recordingModel.stopRecording();
|
||||
|
|
@ -1076,17 +1306,26 @@
|
|||
$('#session-resync').on('click', sessionResync);
|
||||
$('#session-contents').on("click", '[action="delete"]', deleteSession);
|
||||
$('#tracks').on('click', 'div[control="mute"]', toggleMute);
|
||||
$('#recording-start-stop').on('click', startStopRecording)
|
||||
|
||||
$('#recording-start-stop').on('click', startStopRecording);
|
||||
$('#open-a-recording').on('click', openRecording);
|
||||
$('#track-settings').click(function() {
|
||||
configureTrackDialog.showVoiceChatPanel(true);
|
||||
configureTrackDialog.showMusicAudioPanel(true);
|
||||
});
|
||||
$('#close-playback-recording').on('click', closeRecording);
|
||||
$(playbackControls)
|
||||
.on('pause', onPause)
|
||||
.on('play', onPlay)
|
||||
.on('change-position', onChangePlayPosition);
|
||||
}
|
||||
|
||||
this.initialize = function() {
|
||||
this.initialize = function(localRecordingsDialogInstance, recordingFinishedDialogInstance) {
|
||||
localRecordingsDialog = localRecordingsDialogInstance;
|
||||
recordingFinishedDialog = recordingFinishedDialogInstance;
|
||||
context.jamClient.SetVURefreshRate(150);
|
||||
playbackControls = new context.JK.PlaybackControls($('.session-recordings .recording-controls'));
|
||||
events();
|
||||
|
||||
var screenBindings = {
|
||||
'beforeShow': beforeShow,
|
||||
'afterShow': afterShow,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
var clientId = client.clientID;
|
||||
var currentSessionId = null; // Set on join, prior to setting currentSession.
|
||||
var currentSession = null;
|
||||
var currentOrLastSession = null;
|
||||
var subscribers = {};
|
||||
var users = {}; // User info for session participants
|
||||
var rest = context.JK.Rest();
|
||||
|
|
@ -29,6 +30,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
function isPlayingRecording() {
|
||||
// this is the server's state; there is no guarantee that the local tracks
|
||||
// requested from the backend will have corresponding track information
|
||||
return currentSession && currentSession.claimed_recording;
|
||||
}
|
||||
|
||||
function recordedTracks() {
|
||||
if(currentSession && currentSession.claimed_recording) {
|
||||
return currentSession.claimed_recording.recording.recorded_tracks
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function creatorId() {
|
||||
if(!currentSession) {
|
||||
throw "creator is not known"
|
||||
|
|
@ -68,8 +84,8 @@
|
|||
recordingModel.reset();
|
||||
client.JoinSession({ sessionID: sessionId });
|
||||
refreshCurrentSession();
|
||||
server.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, refreshCurrentSession);
|
||||
server.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession);
|
||||
server.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, refreshCurrentSession);
|
||||
server.registerMessageCallback(context.JK.MessageType.SESSION_DEPART, refreshCurrentSession);
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -91,10 +107,14 @@
|
|||
// this may be bad if someone decides to badmouth others in the left-session during this time
|
||||
logger.debug("calling jamClient.LeaveSession for clientId=" + clientId);
|
||||
client.LeaveSession({ sessionID: currentSessionId });
|
||||
deferred = leaveSessionRest(currentSessionId);
|
||||
deferred.done(function() {
|
||||
sessionChanged();
|
||||
});
|
||||
leaveSessionRest(currentSessionId)
|
||||
.done(function() {
|
||||
sessionChanged();
|
||||
deferred.resolve(arguments);
|
||||
})
|
||||
.fail(function() {
|
||||
deferred.reject(arguments);
|
||||
});
|
||||
|
||||
// 'unregister' for callbacks
|
||||
context.jamClient.SessionRegisterCallback("");
|
||||
|
|
@ -146,7 +166,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
// you should only update currentSession with this function
|
||||
function updateCurrentSession(sessionData) {
|
||||
if(sessionData != null) {
|
||||
currentOrLastSession = sessionData;
|
||||
}
|
||||
currentSession = sessionData;
|
||||
}
|
||||
|
||||
|
|
@ -449,12 +473,14 @@
|
|||
|
||||
// Public interface
|
||||
this.id = id;
|
||||
this.recordedTracks = recordedTracks;
|
||||
this.participants = participants;
|
||||
this.joinSession = joinSession;
|
||||
this.leaveCurrentSession = leaveCurrentSession;
|
||||
this.refreshCurrentSession = refreshCurrentSession;
|
||||
this.subscribe = subscribe;
|
||||
this.participantForClientId = participantForClientId;
|
||||
this.isPlayingRecording = isPlayingRecording;
|
||||
this.addTrack = addTrack;
|
||||
this.updateTrack = updateTrack;
|
||||
this.deleteTrack = deleteTrack;
|
||||
|
|
@ -464,6 +490,9 @@
|
|||
this.getCurrentSession = function() {
|
||||
return currentSession;
|
||||
};
|
||||
this.getCurrentOrLastSession = function() {
|
||||
return currentOrLastSession;
|
||||
};
|
||||
};
|
||||
|
||||
})(window,jQuery);
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
notificationId: val.notification_id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
text: val.formatted_msg,
|
||||
date: context.JK.formatDate(val.created_at)
|
||||
date: context.JK.formatDateTime(val.created_at)
|
||||
});
|
||||
|
||||
$('#sidebar-notification-list').append(notificationHtml);
|
||||
|
|
@ -156,9 +156,15 @@
|
|||
acceptFriendRequest({ "friend_request_id": payload.friend_request_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.FRIEND_REQUEST_ACCEPTED) {
|
||||
$notification.find('#div-actions').hide();
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.NEW_USER_FOLLOWER || type === context.JK.MessageType.NEW_BAND_FOLLOWER) {
|
||||
$notification.find('#div-actions').hide();
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.SESSION_INVITATION) {
|
||||
var $action_btn = $notification.find('#btn-notification-action');
|
||||
$action_btn.text('JOIN');
|
||||
|
|
@ -166,6 +172,7 @@
|
|||
openTerms({ "session_id": payload.session_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.JOIN_REQUEST) {
|
||||
var $action_btn = $notification.find('#btn-notification-action');
|
||||
$action_btn.text('APPROVE');
|
||||
|
|
@ -173,6 +180,7 @@
|
|||
approveJoinRequest({ "join_request_id": payload.join_request_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.JOIN_REQUEST_APPROVED) {
|
||||
var $action_btn = $notification.find('#btn-notification-action');
|
||||
$action_btn.text('JOIN');
|
||||
|
|
@ -180,9 +188,31 @@
|
|||
openTerms({ "session_id": payload.session_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.JOIN_REQUEST_REJECTED) {
|
||||
$notification.find('#div-actions').hide();
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.MUSICIAN_SESSION_JOIN || type === context.JK.MessageType.BAND_SESSION_JOIN) {
|
||||
var $action_btn = $notification.find('#btn-notification-action');
|
||||
$action_btn.text('LISTEN');
|
||||
$action_btn.click(function() {
|
||||
listenToSession({ "session_id": payload.session_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.MUSICIAN_RECORDING_SAVED || type === context.JK.MessageType.BAND_RECORDING_SAVED) {
|
||||
var $action_btn = $notification.find('#btn-notification-action');
|
||||
$action_btn.text('LISTEN');
|
||||
$action_btn.click(function() {
|
||||
listenToRecording({ "recording_id": payload.recording_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) {
|
||||
$notification.find('#div-actions').hide();
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.BAND_INVITATION) {
|
||||
var $action_btn = $notification.find('#btn-notification-action');
|
||||
$action_btn.text('ACCEPT');
|
||||
|
|
@ -190,6 +220,7 @@
|
|||
acceptBandInvitation({ "band_invitation_id": payload.band_invitation_id, "band_id": payload.band_id, "notification_id": payload.notification_id });
|
||||
});
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.BAND_INVITATION_ACCEPTED) {
|
||||
$notification.find('#div-actions').hide();
|
||||
}
|
||||
|
|
@ -346,12 +377,7 @@
|
|||
// default handler for incoming notification
|
||||
function handleNotification(payload, type) {
|
||||
var sidebarText;
|
||||
if (type === context.JK.MessageType.SESSION_INVITATION) {
|
||||
sidebarText = payload.sender_name + " has invited you to a session.";
|
||||
}
|
||||
else {
|
||||
sidebarText = payload.msg;
|
||||
}
|
||||
sidebarText = payload.msg;
|
||||
|
||||
// increment displayed notification count
|
||||
incrementNotificationCount();
|
||||
|
|
@ -362,7 +388,7 @@
|
|||
notificationId: payload.notification_id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(payload.photo_url),
|
||||
text: sidebarText,
|
||||
date: context.JK.formatDate(payload.created_at)
|
||||
date: context.JK.formatDateTime(payload.created_at)
|
||||
});
|
||||
|
||||
$('#sidebar-notification-list').prepend(notificationHtml);
|
||||
|
|
@ -421,16 +447,32 @@
|
|||
|
||||
$('.sidebar .invite-friend-row').hoverIntent(inviteHoverIn, inviteHoverOut);
|
||||
|
||||
// friend notifications
|
||||
registerFriendUpdate();
|
||||
registerFriendRequest();
|
||||
registerFriendRequestAccepted();
|
||||
registerMusicianSessionJoin();
|
||||
registerMusicianSessionDepart();
|
||||
registerFriendSessionJoin();
|
||||
registerNewUserFollower();
|
||||
registerNewBandFollower();
|
||||
|
||||
// session invitations
|
||||
registerSessionInvitation();
|
||||
registerSessionEnded();
|
||||
registerJoinRequest();
|
||||
registerJoinRequestApproved();
|
||||
registerJoinRequestRejected();
|
||||
registerSessionJoin();
|
||||
registerSessionDepart();
|
||||
registerMusicianSessionJoin();
|
||||
registerBandSessionJoin();
|
||||
|
||||
// recording notifications
|
||||
registerMusicianRecordingSaved();
|
||||
registerBandRecordingSaved();
|
||||
registerRecordingStarted();
|
||||
registerRecordingEnded();
|
||||
registerRecordingMasterMixComplete();
|
||||
|
||||
// band notifications
|
||||
registerBandInvitation();
|
||||
registerBandInvitationAccepted();
|
||||
|
||||
|
|
@ -450,11 +492,9 @@
|
|||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_UPDATE, function(header, payload) {
|
||||
logger.debug("Handling FRIEND_UPDATE msg " + JSON.stringify(payload));
|
||||
|
||||
// update friends panel in sidebar
|
||||
friends[payload.user_id].online = payload.online;
|
||||
updateFriendList(friends);
|
||||
|
||||
// display notification
|
||||
var online_text = payload.online ? "online" : "offline";
|
||||
app.notify({
|
||||
"title": "Friend is now " + online_text,
|
||||
|
|
@ -470,7 +510,6 @@
|
|||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "New Friend Request",
|
||||
"text": payload.msg,
|
||||
|
|
@ -500,10 +539,8 @@
|
|||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// refresh friends panel
|
||||
initializeFriendsPanel();
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Friend Request Accepted",
|
||||
"text": payload.msg,
|
||||
|
|
@ -512,52 +549,35 @@
|
|||
});
|
||||
}
|
||||
|
||||
function registerMusicianSessionJoin() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, function(header, payload) {
|
||||
logger.debug("Handling MUSICIAN_SESSION_JOIN msg " + JSON.stringify(payload));
|
||||
function registerNewUserFollower() {
|
||||
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_USER_FOLLOWER, function(header, payload) {
|
||||
logger.debug("Handling NEW_USER_FOLLOWER msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Musician Joined Session",
|
||||
"text": payload.username + " has joined the session.",
|
||||
"title": "New Follower",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerMusicianSessionDepart() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, function(header, payload) {
|
||||
logger.debug("Handling MUSICIAN_SESSION_DEPART msg " + JSON.stringify(payload));
|
||||
function registerNewBandFollower() {
|
||||
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_BAND_FOLLOWER, function(header, payload) {
|
||||
logger.debug("Handling NEW_BAND_FOLLOWER msg " + JSON.stringify(payload));
|
||||
|
||||
if(payload.recordingId && context.JK.CurrentSessionModel.recordingModel.isRecording(payload.recordingId)) {
|
||||
context.JK.CurrentSessionModel.recordingModel.onServerStopRecording(payload.recordingId);
|
||||
/**app.notify({
|
||||
"title": "Recording Stopped",
|
||||
"text": payload.username + " has left the session.",
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}); */
|
||||
}
|
||||
else {
|
||||
app.notify({
|
||||
"title": "Musician Left Session",
|
||||
"text": payload.username + " has left the session.",
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
function registerFriendSessionJoin() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_SESSION_JOIN, function(header, payload) {
|
||||
logger.debug("Handling FRIEND_SESSION_JOIN msg " + JSON.stringify(payload));
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Friend Joined Session",
|
||||
"text": payload.username + " has joined a session.",
|
||||
"title": "New Band Follower",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function registerSessionInvitation() {
|
||||
|
|
@ -585,7 +605,6 @@
|
|||
|
||||
participantHtml += "</tbody></table>";
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Session Invitation",
|
||||
"text": participantHtml
|
||||
|
|
@ -608,13 +627,16 @@
|
|||
context.location = '#/session/' + args.session_id;
|
||||
}
|
||||
|
||||
function registerSessionEnded() {
|
||||
// TODO: this should clean up all notifications related to this session
|
||||
}
|
||||
|
||||
function registerJoinRequest() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, function(header, payload) {
|
||||
logger.debug("Handling JOIN_REQUEST msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "New Join Request",
|
||||
"text": payload.msg,
|
||||
|
|
@ -650,7 +672,6 @@
|
|||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Join Request Approved",
|
||||
"text": payload.msg,
|
||||
|
|
@ -669,7 +690,6 @@
|
|||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Join Request Rejected",
|
||||
"text": payload.msg,
|
||||
|
|
@ -678,13 +698,189 @@
|
|||
});
|
||||
}
|
||||
|
||||
function registerSessionJoin() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, function(header, payload) {
|
||||
logger.debug("Handling SESSION_JOIN msg " + JSON.stringify(payload));
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "New Session Participant",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerSessionDepart() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_DEPART, function(header, payload) {
|
||||
logger.debug("Handling SESSION_DEPART msg " + JSON.stringify(payload));
|
||||
|
||||
var recordingId = payload.recording_id;
|
||||
|
||||
if(recordingId&& context.JK.CurrentSessionModel.recordingModel.isRecording(recordingId)) {
|
||||
context.JK.CurrentSessionModel.recordingModel.onServerStopRecording(recordingId);
|
||||
/**app.notify({
|
||||
"title": "Recording Stopped",
|
||||
"text": payload.username + " has left the session.",
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}); */
|
||||
}
|
||||
else {
|
||||
app.notify({
|
||||
"title": "Musician Left Session",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function registerMusicianSessionJoin() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, function(header, payload) {
|
||||
logger.debug("Handling MUSICIAN_SESSION_JOIN msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
app.notify({
|
||||
"title": "Musician Joined Session",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}, {
|
||||
"ok_text": "LISTEN",
|
||||
"ok_callback": listenToSession,
|
||||
"ok_callback_args": {
|
||||
"session_id": payload.session_id
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerBandSessionJoin() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_SESSION_JOIN, function(header, payload) {
|
||||
logger.debug("Handling BAND_SESSION_JOIN msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// TODO: add LISTEN button linking to session
|
||||
app.notify({
|
||||
"title": "Band Joined Session",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}, {
|
||||
"ok_text": "LISTEN",
|
||||
"ok_callback": listenToSession,
|
||||
"ok_callback_args": {
|
||||
"session_id": payload.session_id
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function listenToSession(args) {
|
||||
deleteNotification(args.notification_id);
|
||||
context.location = '#/session/' + args.session_id;
|
||||
}
|
||||
|
||||
function registerMusicianRecordingSaved() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_RECORDING_SAVED, function(header, payload) {
|
||||
logger.debug("Handling MUSICIAN_RECORDING_SAVED msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
app.notify({
|
||||
"title": "Musician Recording Saved",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}, {
|
||||
"ok_text": "LISTEN",
|
||||
"ok_callback": listenToRecording,
|
||||
"ok_callback_args": {
|
||||
"recording_id": payload.recording_id
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function registerBandRecordingSaved() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_RECORDING_SAVED, function(header, payload) {
|
||||
logger.debug("Handling BAND_RECORDING_SAVED msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
app.notify({
|
||||
"title": "Band Recording Saved",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}, {
|
||||
"ok_text": "LISTEN",
|
||||
"ok_callback": listenToRecording,
|
||||
"ok_callback_args": {
|
||||
"recording_id": payload.recording_id
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function listenToRecording(args) {
|
||||
deleteNotification(args.notification_id);
|
||||
context.location = '#/recording/' + args.recording_id;
|
||||
}
|
||||
|
||||
function registerRecordingStarted() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_STARTED, function(header, payload) {
|
||||
logger.debug("Handling RECORDING_STARTED msg " + JSON.stringify(payload));
|
||||
|
||||
app.notify({
|
||||
"title": "Recording Started",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerRecordingEnded() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_ENDED, function(header, payload) {
|
||||
logger.debug("Handling RECORDING_ENDED msg " + JSON.stringify(payload));
|
||||
|
||||
app.notify({
|
||||
"title": "Recording Ended",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerRecordingMasterMixComplete() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE, function(header, payload) {
|
||||
logger.debug("Handling RECORDING_MASTER_MIX_COMPLETE msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
app.notify({
|
||||
"title": "Recording Master Mix Complete",
|
||||
"text": payload.msg,
|
||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||
}, {
|
||||
"ok_text": "SHARE",
|
||||
"ok_callback": shareRecording,
|
||||
"ok_callback_args": {
|
||||
"recording_id": payload.recording_id
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function shareRecording(args) {
|
||||
var recordingId = args.recording_id;
|
||||
}
|
||||
|
||||
function registerBandInvitation() {
|
||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION, function(header, payload) {
|
||||
logger.debug("Handling BAND_INVITATION msg " + JSON.stringify(payload));
|
||||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Band Invitation",
|
||||
"text": payload.msg,
|
||||
|
|
@ -717,7 +913,6 @@
|
|||
|
||||
handleNotification(payload, header.type);
|
||||
|
||||
// display notification
|
||||
app.notify({
|
||||
"title": "Band Invitation Accepted",
|
||||
"text": payload.msg,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,14 @@
|
|||
context.JK = context.JK || {};
|
||||
var logger = context.JK.logger;
|
||||
|
||||
var days = new Array("Sun", "Mon", "Tue",
|
||||
"Wed", "Thu", "Fri", "Sat");
|
||||
|
||||
var months = new Array("January", "February", "March",
|
||||
"April", "May", "June", "July", "August", "September",
|
||||
"October", "November", "December");
|
||||
|
||||
|
||||
context.JK.stringToBool = function(s) {
|
||||
switch(s.toLowerCase()){
|
||||
case "true": case "yes": case "1": return true;
|
||||
|
|
@ -70,6 +78,69 @@
|
|||
instrumentIconMap45[instrumentId] = "../assets/content/icon_instrument_" + icon + "45.png";
|
||||
});
|
||||
|
||||
/**
|
||||
* Associates a help bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
||||
* @param $element The element that should show the help when hovered
|
||||
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.erb
|
||||
* @param data (optional) data for your template, if applicable
|
||||
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
||||
*
|
||||
*/
|
||||
context.JK.helpBubble = function($element, templateName, data, options) {
|
||||
if(!data) {
|
||||
data = {}
|
||||
}
|
||||
var helpText = context._.template($('#template-help-' + templateName).html(), data, { variable: 'data' });
|
||||
|
||||
var holder = $('<div class="hover-bubble help-bubble"></div>');
|
||||
holder.append(helpText);
|
||||
|
||||
context.JK.hoverBubble($element, helpText, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
||||
* @param $element The element that should show the bubble when hovered
|
||||
* @param text the text or jquery element that should be shown as contents of the bubble
|
||||
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
||||
*/
|
||||
context.JK.hoverBubble = function($element, text, options) {
|
||||
if(!text) {
|
||||
logger.error("hoverBubble: no text to attach to $element %o", $element);
|
||||
return;
|
||||
}
|
||||
|
||||
if($element instanceof jQuery) {
|
||||
if ($element.length == 0) {
|
||||
logger.error("hoverBubble: no element specified with text %o", text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var defaultOpts = {
|
||||
fill: '#333',
|
||||
strokeStyle: '#ED3618',
|
||||
spikeLength: 10,
|
||||
spikeGirth: 10,
|
||||
padding: 8,
|
||||
cornerRadius: 0,
|
||||
cssStyles: {
|
||||
fontFamily: 'Raleway, Arial, Helvetica, sans-serif',
|
||||
fontSize: '11px',
|
||||
color:'white',
|
||||
whiteSpace:'normal'
|
||||
}
|
||||
};
|
||||
|
||||
if(options) {
|
||||
options = $.extend(false, defaultOpts, options);
|
||||
}
|
||||
else {
|
||||
options = defaultOpts;
|
||||
}
|
||||
|
||||
$element.bt(text, options);
|
||||
}
|
||||
// Uber-simple templating
|
||||
// var template = "Hey {name}";
|
||||
// var vals = { name: "Jon" };
|
||||
|
|
@ -175,11 +246,46 @@
|
|||
return retVal;
|
||||
}
|
||||
|
||||
context.JK.formatDate = function(dateString) {
|
||||
context.JK.formatDateTime = function(dateString) {
|
||||
var date = new Date(dateString);
|
||||
return date.getFullYear() + "-" + context.JK.padString(date.getMonth()+1, 2) + "-" + context.JK.padString(date.getDate(), 2) + " @ " + date.toLocaleTimeString();
|
||||
}
|
||||
|
||||
// returns Fri May 20, 2013
|
||||
context.JK.formatDate = function(dateString) {
|
||||
var date = new Date(dateString);
|
||||
|
||||
return days[date.getDay()] + ' ' + months[date.getMonth()] + ' ' + context.JK.padString(date.getDate(), 2) + ', ' + date.getFullYear();
|
||||
}
|
||||
|
||||
context.JK.formatTime = function(dateString) {
|
||||
var date = new Date(dateString);
|
||||
return date.toLocaleTimeString();
|
||||
}
|
||||
|
||||
context.JK.prettyPrintSeconds = function(seconds) {
|
||||
// from: http://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
||||
|
||||
// Minutes and seconds
|
||||
var mins = ~~(seconds / 60);
|
||||
var secs = seconds % 60;
|
||||
|
||||
// Hours, minutes and seconds
|
||||
var hrs = ~~(seconds / 3600);
|
||||
var mins = ~~((seconds % 3600) / 60);
|
||||
var secs = seconds % 60;
|
||||
|
||||
// Output like "1:01" or "4:03:59" or "123:03:59"
|
||||
var ret = "";
|
||||
|
||||
if (hrs > 0)
|
||||
ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
|
||||
|
||||
ret += "" + mins + ":" + (secs < 10 ? "0" : "");
|
||||
ret += "" + secs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
context.JK.search = function(query, app, callback) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
|
|
@ -270,7 +376,7 @@
|
|||
return null;
|
||||
}
|
||||
|
||||
var ul = $('<ul class="error-text"></ul>')
|
||||
var ul = $('<ul class="error-text"></ul>');
|
||||
|
||||
$.each(field_errors, function(index, item) {
|
||||
ul.append(context.JK.fillTemplate("<li>{message}</li>", {message: item}))
|
||||
|
|
@ -279,6 +385,22 @@
|
|||
return ul;
|
||||
}
|
||||
|
||||
context.JK.format_all_errors = function(errors_data) {
|
||||
var errors = errors_data["errors"];
|
||||
if(errors == null) return $('<ul class="error-text"><li>unknown error</li></ul>');
|
||||
|
||||
var ul = $('<ul class="error-text"></ul>');
|
||||
|
||||
$.each(errors, function(fieldName, field_errors) {
|
||||
|
||||
$.each(field_errors, function(index, item) {
|
||||
ul.append(context.JK.fillTemplate("<li>{field} {message}</li>", {field: fieldName, message: item}))
|
||||
});
|
||||
});
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Way to verify that a number of parallel tasks have all completed.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
@import 'common.css.scss';
|
||||
|
||||
.account-content-scroller {
|
||||
.account-content-scroller,
|
||||
#account-identity-content-scroller {
|
||||
|
||||
.content-wrapper {
|
||||
padding:10px 35px;
|
||||
padding:10px 30px;
|
||||
}
|
||||
|
||||
.content-wrapper.account {
|
||||
|
|
@ -16,6 +17,7 @@
|
|||
}
|
||||
|
||||
h4 {
|
||||
margin-top:8px;
|
||||
margin-bottom: 10px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
|
@ -57,7 +59,15 @@
|
|||
}
|
||||
|
||||
.account-profile {
|
||||
padding-top:25px;
|
||||
padding-top:20px;
|
||||
|
||||
.avatar_large {
|
||||
position:absolute;
|
||||
float:none;
|
||||
top: -36px;
|
||||
right:0;
|
||||
margin-right:20%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom:15px;
|
||||
|
|
@ -65,17 +75,16 @@
|
|||
|
||||
.location {
|
||||
position:relative;
|
||||
padding-top:25px;
|
||||
}
|
||||
|
||||
#account-change-avatar {
|
||||
position:absolute;
|
||||
top:-27px;
|
||||
right:72px;
|
||||
height:13px;
|
||||
float:right;
|
||||
margin-right:17%;
|
||||
}
|
||||
|
||||
.birth_date {
|
||||
margin-left:40px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +123,7 @@
|
|||
|
||||
.button-orange, .button-grey {
|
||||
line-height:14px;
|
||||
margin-top:6px;
|
||||
margin-right:0;
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +132,7 @@
|
|||
}
|
||||
|
||||
div.field {
|
||||
margin-bottom:27px;
|
||||
margin-bottom:21px;
|
||||
}
|
||||
|
||||
div.profile-instrumentlist table {
|
||||
|
|
|
|||
|
|
@ -273,9 +273,6 @@
|
|||
|
||||
#band-filter-results {
|
||||
margin: 0 10px 5px 10px;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.band-list-result {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@
|
|||
*
|
||||
*= require_self
|
||||
*= require ./ie
|
||||
*= require jquery.bt
|
||||
*= require ./jamkazam
|
||||
*= require ./content
|
||||
*= require ./paginator
|
||||
*= require ./faders
|
||||
*= require ./header
|
||||
#= require ./user_dropdown
|
||||
|
|
@ -29,6 +31,8 @@
|
|||
*= require ./search
|
||||
*= require ./ftue
|
||||
*= require ./invitationDialog
|
||||
*= require ./recordingFinishedDialog
|
||||
*= require ./localRecordingsDialog
|
||||
*= require ./createSession
|
||||
*= require ./genreSelector
|
||||
*= require ./sessionList
|
||||
|
|
|
|||
|
|
@ -88,6 +88,17 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-head {
|
||||
position: absolute;
|
||||
padding:11px 0;
|
||||
}
|
||||
.filter-body {
|
||||
height:100%;
|
||||
width:100%;
|
||||
box-sizing: border-box;
|
||||
padding-top: 49px;
|
||||
}
|
||||
}
|
||||
|
||||
.result-list-button-wrapper {
|
||||
|
|
@ -248,7 +259,7 @@ a.arrow-down {
|
|||
|
||||
#session-controls {
|
||||
width:100%;
|
||||
padding:11px 0px 11px 0px;
|
||||
padding:6px 0px 11px 0px;
|
||||
background-color:#4c4c4c;
|
||||
min-height:20px;
|
||||
overflow-x:scroll;
|
||||
|
|
@ -341,6 +352,8 @@ ul.shortcuts {
|
|||
border-color:#ED3618;
|
||||
}
|
||||
|
||||
|
||||
|
||||
span.arrow-right {
|
||||
display:inline-block;
|
||||
width: 0;
|
||||
|
|
|
|||
|
|
@ -111,20 +111,4 @@
|
|||
padding:10px;
|
||||
border-bottom:solid 1px #999;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
div[layout-id="createSession"] .icheckbuttons {
|
||||
|
||||
margin-top:5px;
|
||||
|
||||
div.iradio_minimal {
|
||||
float:left;
|
||||
}
|
||||
|
||||
label {
|
||||
float:left;
|
||||
margin:0 10px 0 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -461,3 +461,18 @@ div[layout-id=session], div[layout-id=ftue], .no-selection-range {
|
|||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
.icheckbuttons {
|
||||
|
||||
margin-top:5px;
|
||||
|
||||
div.iradio_minimal {
|
||||
float:left;
|
||||
}
|
||||
|
||||
label {
|
||||
float:left;
|
||||
margin:0 10px 0 3px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#local-recordings-dialog {
|
||||
table.local-recordings {
|
||||
tbody {
|
||||
tr:hover {
|
||||
background-color: #400606;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
tr[data-local-state=MISSING], tr[data-local-state=PARTIALLY_MISSING] {
|
||||
background-color:#777;
|
||||
color:#aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -22,14 +22,11 @@
|
|||
|
||||
#musician-filter-results {
|
||||
margin: 0 10px 0px 10px;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
// width: 100%;
|
||||
}
|
||||
|
||||
.musician-wrapper {
|
||||
// overflow: auto;
|
||||
// height: 480px;
|
||||
overflow: initial;
|
||||
height: initial;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
|
@ -37,12 +34,8 @@
|
|||
padding-top: 5px;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
|
||||
#session-controls.musician-filter {
|
||||
padding-top: 6px;
|
||||
}
|
||||
.musician-following {
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
div.paginator {
|
||||
.arrow-right {
|
||||
display:inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
border-left: 4px solid #FFCC00;
|
||||
padding-left:5px;
|
||||
}
|
||||
|
||||
span.arrow-right {
|
||||
border-left: 4px solid #aaa;
|
||||
}
|
||||
|
||||
.arrow-left {
|
||||
display:inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
border-right: 4px solid #FFCC00;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
span.arrow-left {
|
||||
border-right: 4px solid #aaa;
|
||||
}
|
||||
}
|
||||
|
|
@ -196,6 +196,7 @@
|
|||
position:relative;
|
||||
margin:10px 0px 10px 0px;
|
||||
padding-bottom:5px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
|
||||
.profile-social-left {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
#recording-finished-dialog {
|
||||
width:1000px;
|
||||
height:auto;
|
||||
div[purpose=description], div[purpose=is_public], div[purpose=is_downloadable] {
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
label[for=is_downloadable], label[for=is_public], label[for=playback-mode-preview-all], label[for=playback-mode-preview-me] {
|
||||
display:inline;
|
||||
}
|
||||
|
||||
.recording-controls {
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.icheckbuttons {
|
||||
margin-top:20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
.content,
|
||||
.inner-content {
|
||||
clear: both;
|
||||
float: left;
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -232,14 +232,28 @@ table.vu td {
|
|||
|
||||
.session-recording-name-wrapper {
|
||||
position:relative;
|
||||
white-space:nowrap;
|
||||
white-space:nowrap;
|
||||
display:none;
|
||||
|
||||
.session-add {
|
||||
margin-top:9px;
|
||||
}
|
||||
.session-add a {
|
||||
vertical-align:top;
|
||||
outline:none;
|
||||
|
||||
img {
|
||||
margin-top:-3px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.session-recording-name {
|
||||
width:60%;
|
||||
overflow:hidden;
|
||||
margin-top:6px;
|
||||
margin-top:9px;
|
||||
margin-bottom:8px;
|
||||
font-size:16px;
|
||||
}
|
||||
|
|
@ -477,6 +491,38 @@ table.vu td {
|
|||
background-color:#666;
|
||||
}
|
||||
|
||||
.session-mytracks {
|
||||
.track-connection {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.session-recordings {
|
||||
.track-connection {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.track-close {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.recording-controls {
|
||||
display:none;
|
||||
|
||||
.play-button {
|
||||
outline:none;
|
||||
}
|
||||
|
||||
.play-button img.pausebutton {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
#recording-finished-dialog .recording-controls {
|
||||
display:block;
|
||||
}
|
||||
|
||||
|
||||
.voicechat {
|
||||
margin-top:10px;
|
||||
|
|
@ -571,7 +617,7 @@ table.vu td {
|
|||
width:93%;
|
||||
min-width:200px;
|
||||
background-color:#242323;
|
||||
position:relative;
|
||||
position:absolute;
|
||||
font-size:13px;
|
||||
text-align:center;
|
||||
}
|
||||
|
|
@ -593,6 +639,10 @@ table.vu td {
|
|||
margin-top:4px;
|
||||
}
|
||||
|
||||
.recording-time.duration-time {
|
||||
padding-left:2px;
|
||||
}
|
||||
|
||||
.recording-playback {
|
||||
display:inline-block;
|
||||
background-image:url(/assets/content/bkg_playcontrols.png);
|
||||
|
|
@ -601,12 +651,17 @@ table.vu td {
|
|||
width:65%;
|
||||
height:16px;
|
||||
margin-top:2px;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.recording-slider {
|
||||
position:absolute;
|
||||
left:40px;
|
||||
left:0px;
|
||||
top:0px;
|
||||
|
||||
img {
|
||||
position:absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.recording-current {
|
||||
|
|
|
|||
|
|
@ -1,49 +1,49 @@
|
|||
table.findsession-table {
|
||||
margin-top:6px;
|
||||
width:98%;
|
||||
font-size:11px;
|
||||
color:#fff;
|
||||
background-color:#262626;
|
||||
border:solid 1px #4d4d4d;
|
||||
}
|
||||
table.findsession-table, table.local-recordings {
|
||||
margin-top:6px;
|
||||
width:98%;
|
||||
font-size:11px;
|
||||
color:#fff;
|
||||
background-color:#262626;
|
||||
border:solid 1px #4d4d4d;
|
||||
|
||||
.findsession-table th {
|
||||
th {
|
||||
font-weight:300;
|
||||
background-color:#4d4d4d;
|
||||
padding:6px;
|
||||
border-right:solid 1px #333;
|
||||
}
|
||||
}
|
||||
|
||||
.findsession-table td {
|
||||
td {
|
||||
padding:9px 5px 5px 5px;
|
||||
border-right:solid 1px #333;
|
||||
border-top:solid 1px #333;
|
||||
vertical-align:top;
|
||||
white-space:normal;
|
||||
}
|
||||
}
|
||||
|
||||
.findsession-table .noborder {
|
||||
.noborder {
|
||||
border-right:none;
|
||||
}
|
||||
}
|
||||
|
||||
.findsession-table .musicians {
|
||||
.musicians {
|
||||
margin-top:-3px;
|
||||
}
|
||||
}
|
||||
|
||||
.findsession-table .musicians td {
|
||||
.musicians td {
|
||||
border-right:none;
|
||||
border-top:none;
|
||||
padding:3px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
}
|
||||
|
||||
.findsession-table a {
|
||||
a {
|
||||
color:#fff;
|
||||
text-decoration:none;
|
||||
}
|
||||
}
|
||||
|
||||
.findsession-table a:hover {
|
||||
a:hover {
|
||||
color:#227985;
|
||||
}
|
||||
}
|
||||
|
||||
.latency-grey {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
.recording-controls {
|
||||
.playback-mode-buttons {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,8 @@ class ApiClaimedRecordingsController < ApiController
|
|||
respond_to :json
|
||||
|
||||
def index
|
||||
@claimed_recordings = ClaimedRecording.where(:user_id => current_user.id).order("created_at DESC").paginate(page: params[:page])
|
||||
@claimed_recordings = ClaimedRecording.where(:user_id => current_user.id).order("created_at DESC").paginate(page: params[:page], per_page: params[:per_page])
|
||||
response.headers['total-entries'] = @claimed_recordings.total_entries.to_s
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
@ -23,13 +24,13 @@ class ApiClaimedRecordingsController < ApiController
|
|||
end
|
||||
|
||||
def delete
|
||||
begin
|
||||
@claimed_recording.discard(current_user)
|
||||
render :json => {}, :status => 204
|
||||
#begin
|
||||
#@claimed_recording.discard(current_user)
|
||||
#render :json => {}, :status => 204
|
||||
# respond_with responder: ApiResponder, :status => 204
|
||||
rescue
|
||||
render :json => { :message => "claimed_recording could not be deleted" }, :status => 403
|
||||
end
|
||||
#rescue
|
||||
#render :json => { :message => "claimed_recording could not be deleted" }, :status => 403
|
||||
#end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class ApiInvitationsController < ApiController
|
|||
User.save_session_settings(current_user, music_session)
|
||||
|
||||
# send notification
|
||||
Notification.send_session_invitation(receiver.id, current_user, music_session.id)
|
||||
Notification.send_session_invitation(receiver, current_user, music_session.id)
|
||||
respond_with @invitation, :responder => ApiResponder, :location => api_invitation_detail_url(@invitation)
|
||||
|
||||
else
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ class ApiMusicSessionsController < ApiController
|
|||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user
|
||||
before_filter :lookup_session, only: [:show, :update, :delete]
|
||||
before_filter :lookup_session, only: [:show, :update, :delete, :claimed_recording_start, :claimed_recording_stop]
|
||||
skip_before_filter :api_signed_in_user, only: [:perf_upload]
|
||||
|
||||
respond_to :json
|
||||
|
|
@ -122,10 +122,6 @@ class ApiMusicSessionsController < ApiController
|
|||
end
|
||||
end
|
||||
|
||||
def lookup_session
|
||||
@music_session = MusicSession.find(params[:id])
|
||||
end
|
||||
|
||||
def track_index
|
||||
@tracks = Track.index(current_user, params[:id])
|
||||
end
|
||||
|
|
@ -235,8 +231,38 @@ class ApiMusicSessionsController < ApiController
|
|||
# so... just return 200
|
||||
render :json => { :id => @perfdata.id }, :status => 200
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def claimed_recording_start
|
||||
@music_session.claimed_recording_start(current_user, ClaimedRecording.find(params[:claimed_recording_id]))
|
||||
|
||||
if @music_session.errors.any?
|
||||
# we have to do this because api_session_detail_url will fail with a bad @music_session
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @music_session
|
||||
else
|
||||
respond_with @music_session, responder: ApiResponder
|
||||
end
|
||||
end
|
||||
|
||||
def claimed_recording_stop
|
||||
@music_session.claimed_recording_stop
|
||||
|
||||
if @music_session.errors.any?
|
||||
# we have to do this because api_session_detail_url will fail with a bad @music_session
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @music_session
|
||||
else
|
||||
respond_with @music_session, responder: ApiResponder
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lookup_session
|
||||
@music_session = MusicSession.find(params[:id])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
class ApiRecordingsController < ApiController
|
||||
|
||||
before_filter :api_signed_in_user
|
||||
before_filter :look_up_recording, :only => [ :show, :stop, :claim, :keep ]
|
||||
before_filter :look_up_recording, :only => [ :show, :stop, :claim, :discard, :keep ]
|
||||
before_filter :parse_filename, :only => [ :download, :upload_next_part, :upload_sign, :upload_part_complete, :upload_complete ]
|
||||
|
||||
respond_to :json
|
||||
|
||||
@@log = Logging.logger[ApiRecordingsController]
|
||||
|
||||
def index
|
||||
# lists recordings created by for the current user
|
||||
@recordings = Recording.list_recordings(current_user, params[:created_by])
|
||||
end
|
||||
|
||||
# Returns all files this user should be uploading from his client
|
||||
def list_uploads
|
||||
begin
|
||||
result = Recording.list_uploads(current_user, params[:limit], params[:since])
|
||||
puts result.inspect
|
||||
render :json => result, :status => 200
|
||||
rescue
|
||||
render :json => { :message => "could not produce list of files" }, :status => 403
|
||||
|
|
@ -32,15 +36,15 @@ class ApiRecordingsController < ApiController
|
|||
end
|
||||
|
||||
def download
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_track.can_download?(current_user)
|
||||
|
||||
redirect_to @recorded_track.sign_url
|
||||
end
|
||||
|
||||
def start
|
||||
music_session = MusicSession.find(params[:music_session_id])
|
||||
|
||||
unless music_session.users.exists?(current_user)
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless music_session.users.exists?(current_user)
|
||||
|
||||
@recording = Recording.start(music_session, current_user)
|
||||
|
||||
|
|
@ -54,10 +58,6 @@ class ApiRecordingsController < ApiController
|
|||
|
||||
def stop
|
||||
|
||||
unless @recording.users.exists?(current_user)
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
|
||||
@recording.stop
|
||||
|
||||
if @recording.errors.any?
|
||||
|
|
@ -68,10 +68,9 @@ class ApiRecordingsController < ApiController
|
|||
end
|
||||
end
|
||||
|
||||
# keep will kick off a mix, as well as create a claimed recording for the creator
|
||||
# claim will create a claimed recording for the creator
|
||||
def claim
|
||||
claim = @recording.claim(current_user, params[:name], params[:description], Genre.find(params[:genre_id]), params[:is_public], params[:is_downloadable])
|
||||
claim.save
|
||||
claim = @recording.claim(current_user, params[:name], params[:description], Genre.find_by_id(params[:genre]), params[:is_public], params[:is_downloadable])
|
||||
|
||||
if claim.errors.any?
|
||||
response.status = :unprocessable_entity
|
||||
|
|
@ -81,6 +80,12 @@ class ApiRecordingsController < ApiController
|
|||
end
|
||||
end
|
||||
|
||||
# discard will tell the server the user has no interest in the recording
|
||||
def discard
|
||||
@recording.discard(current_user)
|
||||
render :json => {}, :status => 200
|
||||
end
|
||||
|
||||
def upload_next_part
|
||||
length = params[:length]
|
||||
md5 = params[:md5]
|
||||
|
|
@ -141,14 +146,13 @@ class ApiRecordingsController < ApiController
|
|||
private
|
||||
|
||||
def parse_filename
|
||||
@recorded_track = RecordedTrack.find_by_recording_id_and_client_track_id(params[:id], params[:track_id])
|
||||
unless @recorded_track
|
||||
render :json => { :message => ValidationMessages::RECORDING_NOT_FOUND }, :status => 404
|
||||
end
|
||||
@recorded_track = RecordedTrack.find_by_recording_id_and_client_track_id!(params[:id], params[:track_id])
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recorded_track.recording.has_access?(current_user)
|
||||
end
|
||||
|
||||
def look_up_recording
|
||||
@recording = Recording.find(params[:id])
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @recording.has_access?(current_user)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class ApiUsersController < ApiController
|
|||
{:band_musicians => :user},
|
||||
:bands, :instruments])
|
||||
.find(params[:id])
|
||||
|
||||
respond_with @user, responder: ApiResponder, :status => 200
|
||||
end
|
||||
|
||||
|
|
@ -55,8 +56,6 @@ class ApiUsersController < ApiController
|
|||
def update
|
||||
|
||||
@user = User.find(params[:id])
|
||||
|
||||
|
||||
@user.first_name = params[:first_name] if params.has_key?(:first_name)
|
||||
@user.last_name = params[:last_name] if params.has_key?(:last_name)
|
||||
@user.gender = params[:gender] if params.has_key?(:gender)
|
||||
|
|
@ -269,11 +268,11 @@ class ApiUsersController < ApiController
|
|||
id = params[:id]
|
||||
|
||||
if !params[:user_id].nil?
|
||||
User.create_user_following(params[:user_id], id)
|
||||
@user.create_user_following(params[:user_id])
|
||||
respond_with @user, responder: ApiResponder, :location => api_user_following_index_url(@user)
|
||||
|
||||
elsif !params[:band_id].nil?
|
||||
User.create_band_following(params[:band_id], id)
|
||||
@user.create_band_following(params[:band_id])
|
||||
respond_with @user, responder: ApiResponder, :location => api_band_following_index_url(@user)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ class ApiResponder < ActionController::Responder
|
|||
logger.debug("REST API entity has error: #{resource.errors.inspect}")
|
||||
controller.response.status = :unprocessable_entity
|
||||
when post?
|
||||
logger.debug("REST API post")
|
||||
controller.response.status = :created
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
object @claimed_recording
|
||||
|
||||
attributes :id, :name, :is_public, :is_downloadable
|
||||
attributes :id, :name, :description, :is_public, :is_downloadable
|
||||
|
||||
child(:recording => :recording) {
|
||||
attributes :id, :created_at, :duration
|
||||
|
|
@ -15,15 +15,13 @@ child(:recording => :recording) {
|
|||
child(:mixes => :mixes) {
|
||||
attributes :id, :url, :is_completed
|
||||
}
|
||||
}
|
||||
|
||||
child(:recorded_tracks => :recorded_tracks) {
|
||||
attributes :id, :fully_uploaded, :url
|
||||
child(:instrument => :instrument) {
|
||||
attributes :id, :description
|
||||
}
|
||||
child(:user => :user) {
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url
|
||||
child(:recorded_tracks => :recorded_tracks) {
|
||||
attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id
|
||||
|
||||
child(:user => :user) {
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
object @music_session
|
||||
|
||||
attributes :id, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id
|
||||
attributes :id, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id
|
||||
|
||||
node :genres do |item|
|
||||
item.genres.map(&:description)
|
||||
|
|
@ -38,3 +38,30 @@ node(:join_requests, :if => lambda { |music_session| music_session.users.exists?
|
|||
}
|
||||
}
|
||||
end
|
||||
|
||||
# only show currently playing recording data if the current_user is in the session
|
||||
node(:claimed_recording, :if => lambda { |music_session| music_session.users.exists?(current_user) } ) do |music_session|
|
||||
|
||||
child(:claimed_recording => :claimed_recording) {
|
||||
attributes :id, :name, :description, :is_public, :is_downloadable
|
||||
|
||||
child(:recording => :recording) {
|
||||
attributes :id, :created_at, :duration
|
||||
child(:band => :band) {
|
||||
attributes :id, :name
|
||||
}
|
||||
|
||||
child(:mixes => :mixes) {
|
||||
attributes :id, :url, :is_completed
|
||||
}
|
||||
|
||||
child(:recorded_tracks => :recorded_tracks) {
|
||||
attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id
|
||||
|
||||
child(:user => :user) {
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @recordings
|
||||
|
||||
extends "api_recordings_sessions/show"
|
||||
|
|
@ -3,12 +3,9 @@ object @recording
|
|||
attributes :id, :band, :created_at, :duration
|
||||
|
||||
child(:recorded_tracks => :recorded_tracks) {
|
||||
attributes :id, :client_id, :track_id, :user_id, :fully_uploaded, :url
|
||||
child(:instrument => :instrument) {
|
||||
attributes :id, :description
|
||||
}
|
||||
attributes :id, :fully_uploaded, :url, :client_track_id, :client_id, :instrument_id
|
||||
|
||||
child(:user => :user) {
|
||||
attributes :id, :first_name, :last_name, :city, :state, :country, :photo_url
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue