diff --git a/admin/app/controllers/checks_controller.rb b/admin/app/controllers/checks_controller.rb new file mode 100644 index 000000000..52330c2aa --- /dev/null +++ b/admin/app/controllers/checks_controller.rb @@ -0,0 +1,19 @@ +class ChecksController < ApplicationController + + #respond_to :json + + # create or update a client_artifact row + def check_latency_tester + + latency_tester_name = params[:name] + + exists = Connection.where(client_type: Connection::TYPE_LATENCY_TESTER).where(client_id: latency_tester_name).first + + if exists + render :text => "", :status => :ok + else + render :text => "", :status => 404 + end + end + +end \ No newline at end of file diff --git a/admin/config/routes.rb b/admin/config/routes.rb index 05aed06bc..bae57c044 100644 --- a/admin/config/routes.rb +++ b/admin/config/routes.rb @@ -32,6 +32,7 @@ JamAdmin::Application.routes.draw do match '/api/artifacts' => 'artifacts#update_artifacts', :via => :post match '/api/mix/:id/enqueue' => 'admin/mixes#mix_again', :via => :post + match '/api/checks/latency_tester' => 'checks#check_latency_tester', :via => :get mount Resque::Server.new, :at => "/resque" diff --git a/db/manifest b/db/manifest index fd9bab56b..fc5d059bc 100755 --- a/db/manifest +++ b/db/manifest @@ -256,4 +256,6 @@ remove_bpm_from_jamtracks.sql alter_type_columns.sql user_presences_rename.sql add_genre_type.sql +add_description_to_perf_samples.sql +widen_user_authorization_token.sql musician_search.sql diff --git a/db/up/add_description_to_perf_samples.sql b/db/up/add_description_to_perf_samples.sql new file mode 100644 index 000000000..2c1ee462e --- /dev/null +++ b/db/up/add_description_to_perf_samples.sql @@ -0,0 +1 @@ +alter table performance_samples add column description varchar(256) NULL; \ No newline at end of file diff --git a/db/up/recorded_jam_track_tracks.sql b/db/up/recorded_jam_track_tracks.sql new file mode 100644 index 000000000..246b76425 --- /dev/null +++ b/db/up/recorded_jam_track_tracks.sql @@ -0,0 +1,15 @@ +ALTER TABLE recordings ADD COLUMN jam_track_id VARCHAR(64) REFERENCES jam_tracks(id); +ALTER TABLE recordings ADD COLUMN jam_track_initiator_id VARCHAR(64) REFERENCES users(id); + +CREATE TABLE recorded_jam_track_tracks ( + id BIGINT PRIMARY KEY, + user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE, + jam_track_track_id VARCHAR(64), + recording_id VARCHAR(64) NOT NULL, + discard BOOLEAN, + timeline JSON, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE recorded_jam_tracks ALTER COLUMN id SET DEFAULT nextval('tracks_next_tracker_seq'); \ No newline at end of file diff --git a/db/up/widen_user_authorization_token.sql b/db/up/widen_user_authorization_token.sql new file mode 100644 index 000000000..070f67b83 --- /dev/null +++ b/db/up/widen_user_authorization_token.sql @@ -0,0 +1 @@ +alter table user_authorizations ALTER COLUMN token TYPE character varying(2000); \ No newline at end of file diff --git a/web/README.md b/web/README.md index b32f3ab99..f2dccf0a1 100644 --- a/web/README.md +++ b/web/README.md @@ -1,10 +1,4 @@ Jasmine Javascript Unit Tests ============================= -1. Ensure you have the jasmine Gem installed; -$ bundle - -2. Start the jasmine server (defaults to :8888) -$ rake jasmine - -Open browser to localhost:8888 +Open browser to localhost:3000/teaspoon diff --git a/web/app/assets/javascripts/profile.js b/web/app/assets/javascripts/profile.js index 7ce15f46e..20efadbf6 100644 --- a/web/app/assets/javascripts/profile.js +++ b/web/app/assets/javascripts/profile.js @@ -27,10 +27,21 @@ var $studioCount = $screen.find('#studio-count'); // performance samples - var $noSamples = $screen.find('no-samples'); + var $noSamples = $screen.find('#no-samples'); + var $jamkazamSamples = $screen.find('#jamkazam-samples'); + var $soundCloudSamples = $screen.find('#soundcloud-samples'); + var $youTubeSamples = $screen.find('#youtube-samples'); // online presence - var $noOnlinePresence = $screen.find('no-online-presence'); + var $noOnlinePresence = $screen.find('#no-online-presence'); + var $userWebsite = $screen.find('#user-website'); + var $soundCloudPresence = $screen.find('#soundcloud-presence'); + var $reverbNationPresence = $screen.find('#reverbnation-presence'); + var $bandCampPresence = $screen.find('#bandcamp-presence'); + var $fandalismPresence = $screen.find('#fandalism-presence'); + var $soundCloudPresence = $screen.find('#youtube-presence'); + var $soundCloudPresence = $screen.find('#facebook-presence'); + var $youTubePresence = $screen.find('#twitter-presence'); // current interests var $noInterests = $screen.find('#no-interests'); @@ -43,10 +54,10 @@ var $cowritingSection = $screen.find('#cowriting'); var $cowritingDetails = $screen.find('#cowriting-details'); - var $traditionalBandSection = $screen.find("#traditional-band"); + var $traditionalBandSection = $screen.find('#traditional-band'); var $traditionalBandDetails = $screen.find('#traditional-band-details'); - var $virtualBandSection = $screen.find("#virtual-band"); + var $virtualBandSection = $screen.find('#virtual-band'); var $virtualBandDetails = $screen.find('#virtual-band-details'); // tabs @@ -483,6 +494,23 @@ } else { $noSamples.hide(); + + // show samples section + var jamkazamSamples = profileUtils.jamkazamSamples(user.performance_samples); + var soundCloudSamples = profileUtils.soundCloudSamples(user.performance_samples); + var youTubeSamples = profileUtils.youTubeSamples(user.performance_samples); + + $.each(jamkazamSamples, function(index, sample) { + $jamkazamSamples.append("" + sample.claimed_recording.name + ""); + }); + + $.each(soundCloudSamples, function(index, sample) { + $soundCloudSamples.append("" + sample.service_id + ""); + }); + + $.each(youTubeSamples, function(index, sample) { + $youTubeSamples.append("" + sample.service_id + ""); + }); } // online presences @@ -491,7 +519,15 @@ $noOnlinePresence.show(); } else { - $noOnlinePresence.hide(); + $noOnlinePresence.hide(); + + if (user.website) { + $userWebsite.append(""); + } + + $.each(onlinePresences, function(index, presence) { + + }); } // current interests diff --git a/web/app/assets/javascripts/profile_utils.js b/web/app/assets/javascripts/profile_utils.js index 8c1eba1a1..32b5ce542 100644 --- a/web/app/assets/javascripts/profile_utils.js +++ b/web/app/assets/javascripts/profile_utils.js @@ -18,9 +18,21 @@ var COWRITING_GENRE_TYPE = 'cowriting'; // performance samples - var JAMKAZAM = 'jamkazam'; - var SOUNDCLOUD = 'soundcloud'; - var YOUTUBE = 'youtube'; + var SAMPLE_TYPES = { + JAMKAZAM: {description: "jamkazam"}, + SOUNDCLOUD: {description: "soundcloud"}, + YOUTUBE: {description: "youtube"} + }; + + var ONLINE_PRESENCE_TYPES = { + SOUNDCLOUD: {description: "soundcloud"}, + REVERBNATION: {description: "reverbnation"}, + BANDCAMP: {description: "bandcamp"}, + FANDALISM: {description: "fandalism"}, + YOUTUBE: {description: "youtube"}, + FACEBOOK: {description: "facebook"}, + TWITTER: {description: "twitter"} + }; var USER_TYPE = 'JamRuby::User'; @@ -148,7 +160,7 @@ profileUtils.jamkazamSamples = function(samples) { var matches = $.grep(samples, function(s) { - return s.service_type === JAMKAZAM; + return s.service_type === SAMPLE_TYPES.JAMKAZAM.description; }); return matches; @@ -156,7 +168,7 @@ profileUtils.soundCloudSamples = function(samples) { var matches = $.grep(samples, function(s) { - return s.service_type === SOUNDCLOUD; + return s.service_type === SAMPLE_TYPES.SOUNDCLOUD.description; }); return matches; @@ -164,7 +176,63 @@ profileUtils.youTubeSamples = function(samples) { var matches = $.grep(samples, function(s) { - return s.service_type === YOUTUBE; + return s.service_type === SAMPLE_TYPES.YOUTUBE.description; + }); + + return matches; + } + + profileUtils.soundCloudPresences = function(presences) { + var matches = $.grep(presences, function(p) { + return p.service_type === ONLINE_PRESENCE_TYPES.SOUNDCLOUD.description; + }); + + return matches; + } + + profileUtils.reverbNationPresences = function(presences) { + var matches = $.grep(presences, function(p) { + return p.service_type === ONLINE_PRESENCE_TYPES.REVERBNATION.description; + }); + + return matches; + } + + profileUtils.bandCampPresences = function(presences) { + var matches = $.grep(presences, function(p) { + return p.service_type === ONLINE_PRESENCE_TYPES.BANDCAMP.description; + }); + + return matches; + } + + profileUtils.fandalismPresences = function(presences) { + var matches = $.grep(presences, function(p) { + return p.service_type === ONLINE_PRESENCE_TYPES.FANDALISM.description; + }); + + return matches; + } + + profileUtils.youTubePresences = function(presences) { + var matches = $.grep(presences, function(p) { + return p.service_type === ONLINE_PRESENCE_TYPES.YOUTUBE.description; + }); + + return matches; + } + + profileUtils.facebookPresences = function(presences) { + var matches = $.grep(presences, function(p) { + return p.service_type === ONLINE_PRESENCE_TYPES.FACEBOOK.description; + }); + + return matches; + } + + profileUtils.twitterPresences = function(presences) { + var matches = $.grep(presences, function(p) { + return s.service_type === ONLINE_PRESENCE_TYPES.TWITTER.description; }); return matches; diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index d91ebf0d5..b47946641 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -890,8 +890,11 @@ var mediaType = mixer.media_type; var groupId = mixer.group_id; - // mediaType == null is for backwards compat with older clients. Can be removed soon - if(mediaType == null || mediaType == "" || mediaType == 'RecordingTrack') { + if(mediaType == 'MetronomeTrack' || groupId==ChannelGroupIds.MetronomeGroup) { + // Metronomes come across with a blank media type, so check group_id: + metronomeTrackMixers.push(mixer); + } + else if(mediaType == null || mediaType == "" || mediaType == 'RecordingTrack') { // additional check; if we can match an id in backing tracks or recorded backing track, // we need to remove it from the recorded track set, but move it to the backing track set @@ -922,9 +925,6 @@ } else if(mediaType == 'PeerMediaTrack' || mediaType == 'BackingTrack') { // BackingTrack backingTrackMixers.push(mixer); - } else if(mediaType == 'MetronomeTrack' || groupId==ChannelGroupIds.MetronomeGroup) { - // Metronomes come across with a blank media type, so check group_id: - metronomeTrackMixers.push(mixer); } else if(mediaType == 'JamTrack') { jamTrackMixers.push(mixer); mixer.group_id == ChannelGroupIds.MediaTrackGroup; @@ -1027,7 +1027,12 @@ if(isOpener) { var oppositeMixer = getMixerByResourceId(mixer.rid, MIX_MODES.PERSONAL); + var mixerId = mixer.id + "," + oppositeMixer.uniqueId } + else { + var mixerId = mixer.id; + } + var shortFilename = context.JK.getNameOfFile(backingTrack.filename); if(!sessionModel.isPlayingRecording()) { @@ -1067,7 +1072,7 @@ trackData.gainPercent = gainPercent; trackData.muteClass = muteClass; - trackData.mixerId = mixer.id + "," + oppositeMixer.uniqueId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) + trackData.mixerId = mixerId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) trackData.vuMixerId = mixer.id; // the master mixer controls the VUs for recordings (no personal controls in either master or personal mode) trackData.muteMixerId = mixer.id; // the master mixer controls the mute for recordings (no personal controls in either master or personal mode) trackData.mediaTrackOpener = isOpener; @@ -1132,7 +1137,12 @@ if(isOpener) { var oppositeMixer = getMixerByResourceId(mixer.rid, MIX_MODES.PERSONAL); + var mixerId = mixer.id + "," + oppositeMixer.uniqueId } + else { + var mixerId = mixer.id; + } + // Default trackData to participant + no Mixer state. var trackData = { trackId: oneOfTheTracks.id, @@ -1156,7 +1166,7 @@ } trackData.gainPercent = gainPercent; trackData.muteClass = muteClass; - trackData.mixerId = mixer.id + "," + oppositeMixer.uniqueId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) + trackData.mixerId = mixerId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) trackData.vuMixerId = mixer.id; // the master mixer controls the VUs for recordings (no personal controls in either master or personal mode) trackData.muteMixerId = mixer.id; // the master mixer controls the mute for recordings (no personal controls in either master or personal mode) trackData.mediaTrackOpener = isOpener; @@ -1235,8 +1245,13 @@ if(isOpener) { var oppositeMixer = getMixerByResourceId(mixer.rid, MIX_MODES.PERSONAL); + var mixerId = mixer.id + "," + oppositeMixer.uniqueId } - + else { + var mixerId = mixer.id; + } + + // Default trackData to participant + no Mixer state. var trackData = { trackId: "MS" + oneOfTheTracks.id, @@ -1261,7 +1276,7 @@ } trackData.gainPercent = gainPercent; trackData.muteClass = muteClass; - trackData.mixerId = mixer.id + "," + oppositeMixer.uniqueId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) + trackData.mixerId = mixerId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) trackData.vuMixerId = mixer.id; // the master mixer controls the VUs for recordings (no personal controls in either master or personal mode) trackData.muteMixerId = mixer.id; // the master mixer controls the mute for recordings (no personal controls in either master or personal mode) trackData.mediaTrackOpener = isOpener; @@ -1338,6 +1353,10 @@ if(isOpener) { var oppositeMixer = getMixerByResourceId(mixer.rid, MIX_MODES.PERSONAL); + var mixerId = mixer.id + "," + oppositeMixer.uniqueId + } + else { + var mixerId = mixer.id; } // Default trackData to participant + no Mixer state. @@ -1363,7 +1382,7 @@ } trackData.gainPercent = gainPercent; trackData.muteClass = muteClass; - trackData.mixerId = mixer.id + "," + oppositeMixer.uniqueId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) + trackData.mixerId = mixerId; // the master mixer controls the volume control for recordings (no personal controls in either master or personal mode) trackData.vuMixerId = mixer.id; // the master mixer controls the VUs for recordings (no personal controls in either master or personal mode) trackData.muteMixerId = mixer.id; // the master mixer controls the mute for recordings (no personal controls in either master or personal mode) trackData.mediaControlsDisabled = !isOpener; @@ -1961,11 +1980,22 @@ rest.openBackingTrack({id: context.JK.CurrentSessionModel.id(), backing_track_path: result.file}) .done(function(response) { var openResult = context.jamClient.SessionOpenBackingTrackFile(result.file, false); - //context.JK.CurrentSessionModel.refreshCurrentSession(true); - sessionModel.setBackingTrack(result.file); + + if(openResult) { + sessionModel.setBackingTrack(result.file); + } + else { + app.notify({ + "title": "Couldn't Open Backing Track", + "text": "Is the file a valid audio file?", + "icon_url": "/assets/content/icon_alert_big.png" + }); + closeBackingTrack(); + } + }) .fail(function(jqXHR) { - app.notifyServerError(jqXHR, "Unable to Open BackingTrack For Playback"); + app.notifyServerError(jqXHR, "Unable to Open Backing Track For Playback"); }) } else { @@ -2110,7 +2140,11 @@ context.trackVolumeObject.name = mixer.name; context.trackVolumeObject.record = mixer.record; context.trackVolumeObject.volL = mixer.volume_left; - context.trackVolumeObject.volR = mixer.volume_right; + + // today we treat all tracks as mono, but this is required to make a stereo track happy + //context.trackVolumeObject.volR = mixer.volume_right; + context.trackVolumeObject.volR = mixer.volume_left; + context.trackVolumeObject.loop = mixer.loop; // trackVolumeObject doesn't have a place for range min/max currentMixerRangeMin = mixer.range_low; @@ -2424,8 +2458,6 @@ rest.openMetronome({id: sessionModel.id()}) .done(function() { context.jamClient.SessionOpenMetronome(120, "Click", 1, 0) - context.JK.CurrentSessionModel.refreshCurrentSession(true) - context.JK.CurrentSessionModel.refreshCurrentSession(true) }) .fail(function(jqXHR) { logger.debug(jqXHR, jqXHR) @@ -2487,8 +2519,8 @@ }) .fail(function(jqXHR) { app.notify({ - "title": "Couldn't Close BackingTrack", - "text": "Couldn't inform the server to close BackingTrack. msg=" + jqXHR.responseText, + "title": "Couldn't Close Backing Track", + "text": "Couldn't inform the server to close Backing Track. msg=" + jqXHR.responseText, "icon_url": "/assets/content/icon_alert_big.png" }); }); diff --git a/web/app/views/api_users/profile_show.rabl b/web/app/views/api_users/profile_show.rabl index c88dfa048..0ad7585f1 100644 --- a/web/app/views/api_users/profile_show.rabl +++ b/web/app/views/api_users/profile_show.rabl @@ -8,7 +8,7 @@ child :online_presences => :online_presences do end child :performance_samples => :performance_samples do - attributes :id, :url, :service_type, :claimed_recording_id, :service_id + attributes :id, :url, :service_type, :claimed_recording_id, :service_id, :description child :claimed_recording => :claimed_recording do attributes :name diff --git a/web/app/views/clients/_profile.html.erb b/web/app/views/clients/_profile.html.erb index 4224184b0..e95e22c45 100644 --- a/web/app/views/clients/_profile.html.erb +++ b/web/app/views/clients/_profile.html.erb @@ -121,6 +121,15 @@
None specified
+
+
+ +
+
+ +
+
+

@@ -128,6 +137,30 @@
None specified
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+

@@ -201,7 +234,7 @@

- +