├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── dialogflow ├── README.md └── mixlab │ ├── agent.json │ ├── entities │ ├── genre.json │ ├── genre_entries_en.json │ ├── instrument.json │ ├── instrument_entries_en.json │ ├── sfx.json │ ├── sfx_entries_en.json │ ├── solo.json │ └── solo_entries_en.json │ ├── intents │ ├── addSound.json │ ├── addSound_usersays_en.json │ ├── allInstruments.json │ ├── allInstruments_usersays_en.json │ ├── clear.json │ ├── clear_usersays_en.json │ ├── exit.json │ ├── fallback.json │ ├── getSuggestions - more.json │ ├── getSuggestions - more_usersays_en.json │ ├── getSuggestions.json │ ├── getSuggestions_usersays_en.json │ ├── increaseDuration.json │ ├── increaseDuration_usersays_en.json │ ├── normalSpeed.json │ ├── normalSpeed_usersays_en.json │ ├── playAgain.json │ ├── playAgain_usersays_en.json │ ├── removeInstrument.json │ ├── removeInstrument_usersays_en.json │ ├── replaceInstrument.json │ ├── replaceInstrument_usersays_en.json │ ├── singleInstrument.json │ ├── singleInstrument_usersays_en.json │ ├── slowDown.json │ ├── slowDown_usersays_en.json │ ├── speedUp.json │ ├── speedUp_usersays_en.json │ ├── superFast.json │ ├── superFast_usersays_en.json │ ├── superSlow.json │ ├── superSlow_usersays_en.json │ ├── volumeDown.json │ ├── volumeDown_usersays_en.json │ ├── volumeUp.json │ ├── volumeUp_usersays_en.json │ ├── welcome - no.json │ ├── welcome - no_usersays_en.json │ ├── welcome - yes.json │ ├── welcome - yes_usersays_en.json │ ├── welcome.json │ ├── whoMadeDis.json │ └── whoMadeDis_usersays_en.json │ └── package.json ├── images └── mixlab.jpg ├── webhook ├── .eslintrc.js ├── README.md ├── add-remove.js ├── chirp-session-manager.js ├── cors.json ├── firebasedatabase.js ├── followups.js ├── index.js ├── intent-handler.js ├── logging.js ├── lookup.js ├── package-lock.json ├── package.json ├── response.js ├── sharing-card.js ├── simple-actions.js ├── speed.js ├── test-data.json ├── volume.js └── welcome.js └── website ├── .angular-cli.json ├── .bowerrc ├── .editorconfig ├── .gitignore ├── README.md ├── app.yaml ├── bower.json ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── share.sh ├── src ├── app │ ├── app-routing-transitions.ts │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── classes │ │ ├── stem-player.ts │ │ └── stem.ts │ ├── components │ │ ├── close-button │ │ │ ├── close-button.component.html │ │ │ ├── close-button.component.scss │ │ │ ├── close-button.component.spec.ts │ │ │ └── close-button.component.ts │ │ ├── fallback │ │ │ ├── fallback.component.html │ │ │ ├── fallback.component.scss │ │ │ ├── fallback.component.spec.ts │ │ │ └── fallback.component.ts │ │ ├── loader │ │ │ ├── loader.component.html │ │ │ ├── loader.component.scss │ │ │ ├── loader.component.spec.ts │ │ │ └── loader.component.ts │ │ ├── multitrack-editor │ │ │ ├── multitrack-editor.component.html │ │ │ ├── multitrack-editor.component.scss │ │ │ ├── multitrack-editor.component.spec.ts │ │ │ └── multitrack-editor.component.ts │ │ ├── social │ │ │ ├── social.component.html │ │ │ ├── social.component.scss │ │ │ ├── social.component.spec.ts │ │ │ └── social.component.ts │ │ ├── tooltip │ │ │ ├── tooltip.component.html │ │ │ ├── tooltip.component.scss │ │ │ ├── tooltip.component.spec.ts │ │ │ └── tooltip.component.ts │ │ ├── visual-tracks │ │ │ ├── shader_lib.ts │ │ │ ├── text-texture.ts │ │ │ ├── visual-track-fragment.ts │ │ │ ├── visual-track-presets.ts │ │ │ ├── visual-track-vert.ts │ │ │ ├── visual-track.ts │ │ │ └── visual-tracks.ts │ │ └── volume-button │ │ │ ├── volume-button.component.html │ │ │ ├── volume-button.component.scss │ │ │ ├── volume-button.component.spec.ts │ │ │ └── volume-button.component.ts │ ├── guards │ │ └── jam-resolve.guard.ts │ ├── interfaces │ │ ├── intent.ts │ │ ├── stem.ts │ │ └── track.ts │ ├── mock │ │ ├── suggestions.ts │ │ └── tracks.ts │ ├── pipes │ │ └── safe.pipe.ts │ ├── services │ │ ├── events.service.ts │ │ ├── fallback.service.ts │ │ ├── intent.service.ts │ │ ├── stem.service.ts │ │ └── suggestion.service.ts │ └── states │ │ ├── about │ │ ├── about.component.html │ │ ├── about.component.scss │ │ ├── about.component.spec.ts │ │ └── about.component.ts │ │ ├── home │ │ ├── home.component.html │ │ ├── home.component.scss │ │ ├── home.component.spec.ts │ │ └── home.component.ts │ │ ├── jam │ │ ├── jam.component.html │ │ ├── jam.component.scss │ │ ├── jam.component.spec.ts │ │ └── jam.component.ts │ │ └── link │ │ ├── link.component.html │ │ ├── link.component.scss │ │ ├── link.component.spec.ts │ │ └── link.component.ts ├── assets │ ├── .gitkeep │ ├── images │ │ ├── arrow-left.svg │ │ ├── badge.svg │ │ ├── bubble.svg │ │ ├── caret.svg │ │ ├── close.svg │ │ ├── fallback.jpg │ │ ├── favicons │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-256x256.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── browserconfig.xml │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon.ico │ │ │ ├── manifest.json │ │ │ └── mstile-150x150.png │ │ ├── google-home.png │ │ ├── icon-facebook.svg │ │ ├── icon-google.svg │ │ ├── icon-link.svg │ │ ├── icon-mic.svg │ │ ├── icon-twitter.svg │ │ ├── logo.svg │ │ ├── mic.svg │ │ ├── mixlab.svg │ │ ├── mute.svg │ │ ├── play.svg │ │ ├── share.jpg │ │ ├── tagline.svg │ │ └── volume.svg │ ├── scss │ │ ├── _colors.scss │ │ ├── _grid.scss │ │ ├── _mixins.scss │ │ ├── _typography.scss │ │ ├── _variables.scss │ │ └── shared.scss │ ├── share-jam.html │ ├── silence.mp3 │ ├── third_party │ │ ├── AudioRecorder_edited.js │ │ ├── METADATA │ │ └── webrtc-audio-recording │ │ │ ├── AudioRecorder.js │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ └── package.json │ └── voice-button.html ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── index.html ├── main.ts ├── polyfills.ts ├── styles.scss ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | */node_modules/ 3 | npm-debug.log 4 | .idea 5 | .idea/ 6 | _from_yotam/* 7 | */_test 8 | stitcher/tmp/ 9 | stitcher/audio/ 10 | *.asd 11 | _github/ 12 | */firebase_credentials.json -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult [GitHub Help] for more 22 | information on using pull requests. 23 | 24 | [GitHub Help]: https://help.github.com/articles/about-pull-requests/ -------------------------------------------------------------------------------- /dialogflow/README.md: -------------------------------------------------------------------------------- 1 | Dialogflow Export 2 | === 3 | 4 | This directory contains the zip file needed to Restore an app in Dialogflow. 5 | 6 | It was exported from the production version of Mix Lab, and slightly modified for generic use. 7 | 8 | In order to work with your own application, make sure to update `googleAssistant.project` and `webhook.url` 9 | in the agent.json file. -------------------------------------------------------------------------------- /dialogflow/mixlab/agent.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "", 3 | "language": "en", 4 | "googleAssistant": { 5 | "googleAssistantCompatible": true, 6 | "project": "say-to-play", 7 | "welcomeIntentSignInRequired": false, 8 | "startIntents": [], 9 | "systemIntents": [], 10 | "endIntentIds": [ 11 | "1af4b409-7a90-4da9-a1fd-a619f8ef801a" 12 | ], 13 | "oAuthLinking": { 14 | "required": false, 15 | "grantType": "AUTH_CODE_GRANT" 16 | }, 17 | "voiceType": "MALE_1", 18 | "capabilities": [], 19 | "protocolVersion": "V2" 20 | }, 21 | "defaultTimezone": "America/New_York", 22 | "webhook": { 23 | "url": "https://us-central1-say-to-play.cloudfunctions.net/webhook", 24 | "headers": { 25 | "": "" 26 | }, 27 | "available": true, 28 | "useForDomains": false, 29 | "cloudFunctionsEnabled": false, 30 | "cloudFunctionsInitialized": false 31 | }, 32 | "isPrivate": true, 33 | "customClassifierMode": "use.after", 34 | "mlMinConfidence": 0.3, 35 | "supportedLanguages": [] 36 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/entities/genre.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "716bc528-64dc-47f2-b9be-fd83b76a8917", 3 | "name": "genre", 4 | "isOverridable": true, 5 | "isEnum": false, 6 | "automatedExpansion": false 7 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/entities/instrument.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "69363b22-ce88-4832-8b3f-c8547899f66c", 3 | "name": "instrument", 4 | "isOverridable": true, 5 | "isEnum": false, 6 | "automatedExpansion": false 7 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/entities/sfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "128ada5e-690d-4940-859c-5a044f81d9d2", 3 | "name": "sfx", 4 | "isOverridable": true, 5 | "isEnum": false, 6 | "automatedExpansion": false 7 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/entities/solo.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cd48475c-e07c-418c-a965-ceabe50104a0", 3 | "name": "solo", 4 | "isOverridable": true, 5 | "isEnum": true, 6 | "automatedExpansion": false 7 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/entities/solo_entries_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "value": "solo", 4 | "synonyms": [ 5 | "solo" 6 | ] 7 | } 8 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/addSound.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "334d2ac5-b715-459b-9153-c3708623c971", 3 | "name": "addSound", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "addInstrument", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "380cc58c-733d-4f59-ae55-ce9523ca7466", 14 | "required": false, 15 | "dataType": "@instrument", 16 | "name": "instrument", 17 | "value": "$instrument", 18 | "prompts": [ 19 | { 20 | "lang": "en", 21 | "value": "What kind of instrument?" 22 | }, 23 | { 24 | "lang": "en", 25 | "value": "Which instrument?" 26 | }, 27 | { 28 | "lang": "en", 29 | "value": "What should play?" 30 | } 31 | ], 32 | "isList": false 33 | }, 34 | { 35 | "id": "642a7f89-57c9-4345-b4b9-8f8b71aff87f", 36 | "dataType": "@genre", 37 | "name": "genre", 38 | "value": "$genre", 39 | "isList": false 40 | }, 41 | { 42 | "id": "169e695f-9ed6-474b-95ab-2f0ae5c2fe49", 43 | "dataType": "@solo", 44 | "name": "solo", 45 | "value": "$solo", 46 | "isList": false 47 | }, 48 | { 49 | "id": "24d1d30c-9f1d-4819-8f63-5f132de6e425", 50 | "dataType": "@sfx", 51 | "name": "sfx", 52 | "value": "$sfx", 53 | "isList": false 54 | } 55 | ], 56 | "messages": [ 57 | { 58 | "type": "simple_response", 59 | "platform": "google", 60 | "lang": "en", 61 | "customizeAudio": true, 62 | "items": [ 63 | { 64 | "textToSpeech": "$filler", 65 | "displayText": "Added!" 66 | }, 67 | { 68 | "textToSpeech": "$filler", 69 | "displayText": "Sure, added!" 70 | } 71 | ] 72 | } 73 | ], 74 | "defaultResponsePlatforms": { 75 | "google": false 76 | }, 77 | "speech": [] 78 | } 79 | ], 80 | "priority": 500000, 81 | "webhookUsed": true, 82 | "webhookForSlotFilling": false, 83 | "lastUpdate": 1508956076149, 84 | "fallbackIntent": false, 85 | "events": [] 86 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/allInstruments.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "7ff8421f-4dbe-4e85-880d-b3d360f63b2f", 3 | "name": "allInstruments", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "allInstruments", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "339b1933-996b-432e-b483-5070c29a84ac", 14 | "dataType": "@genre", 15 | "name": "genres", 16 | "value": "$genres", 17 | "isList": true 18 | } 19 | ], 20 | "messages": [ 21 | { 22 | "type": "simple_response", 23 | "platform": "google", 24 | "lang": "en", 25 | "customizeAudio": true, 26 | "items": [ 27 | { 28 | "textToSpeech": "$filler", 29 | "displayText": "Here ya go!" 30 | }, 31 | { 32 | "textToSpeech": "$filler", 33 | "displayText": "What a great idea!" 34 | } 35 | ] 36 | } 37 | ], 38 | "defaultResponsePlatforms": {}, 39 | "speech": [] 40 | } 41 | ], 42 | "priority": 500000, 43 | "webhookUsed": true, 44 | "webhookForSlotFilling": false, 45 | "lastUpdate": 1508965964, 46 | "fallbackIntent": false, 47 | "events": [] 48 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/clear.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "d79de02a-778a-4af7-8002-71fcab7d655e", 3 | "name": "clear", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "clear", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "969e87db-31d5-4b62-8285-8a2ecf62cbfc", 14 | "dataType": "@genre", 15 | "name": "genre", 16 | "value": "$genre", 17 | "isList": false 18 | } 19 | ], 20 | "messages": [ 21 | { 22 | "type": "simple_response", 23 | "platform": "google", 24 | "lang": "en", 25 | "items": [ 26 | { 27 | "textToSpeech": "Alright, let’s start fresh. What do you want to add?" 28 | }, 29 | { 30 | "textToSpeech": "Clean slate. I like it. What do you want to start with?" 31 | }, 32 | { 33 | "textToSpeech": "Starting a new mix. What should we kick it off with?" 34 | } 35 | ] 36 | }, 37 | { 38 | "type": "simple_response", 39 | "platform": "google", 40 | "lang": "en", 41 | "items": [ 42 | { 43 | "textToSpeech": "There’s nothing playing, but sure, here’s more nothing." 44 | }, 45 | { 46 | "textToSpeech": "How can you clear that which is already clear?" 47 | } 48 | ] 49 | } 50 | ], 51 | "defaultResponsePlatforms": {}, 52 | "speech": [] 53 | } 54 | ], 55 | "priority": 500000, 56 | "webhookUsed": true, 57 | "webhookForSlotFilling": false, 58 | "lastUpdate": 1509390944, 59 | "fallbackIntent": false, 60 | "events": [] 61 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/exit.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1af4b409-7a90-4da9-a1fd-a619f8ef801a", 3 | "name": "exit", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": "simple_response", 15 | "platform": "google", 16 | "lang": "en", 17 | "customizeAudio": true, 18 | "textToSpeech": "Let\u0027s jam again soon!", 19 | "displayText": "Let\u0027s jam again soon!" 20 | } 21 | ], 22 | "defaultResponsePlatforms": {}, 23 | "speech": [] 24 | } 25 | ], 26 | "priority": 500000, 27 | "webhookUsed": false, 28 | "webhookForSlotFilling": false, 29 | "lastUpdate": 1510003443246, 30 | "fallbackIntent": false, 31 | "events": [ 32 | { 33 | "name": "actions_intent_CANCEL" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/fallback.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "d42188a4-c110-4ec2-9da3-08af0d12832e", 3 | "name": "fallback", 4 | "auto": false, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "input.unknown", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": 0, 15 | "lang": "en", 16 | "speech": [ 17 | "I’m sorry, I didn’t pick that up. Maybe try to say that another way?", 18 | "My ears aren’t too good from years of DJing. Want to try asking that differently?", 19 | "Not sure if I heard you correctly. Can you try saying that another way?" 20 | ] 21 | } 22 | ], 23 | "defaultResponsePlatforms": { 24 | "google": true 25 | }, 26 | "speech": [] 27 | } 28 | ], 29 | "priority": 500000, 30 | "webhookUsed": true, 31 | "webhookForSlotFilling": false, 32 | "lastUpdate": 1508969865, 33 | "fallbackIntent": true, 34 | "events": [] 35 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/getSuggestions - more.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "35733d52-7a71-4371-98e9-b2383e75ee06", 3 | "parentId": "09a1f69e-f9a5-48c6-8f9c-dc9f8a58de9b", 4 | "rootParentId": "09a1f69e-f9a5-48c6-8f9c-dc9f8a58de9b", 5 | "name": "getSuggestions - more", 6 | "auto": true, 7 | "contexts": [ 8 | "getSuggestions-followup" 9 | ], 10 | "responses": [ 11 | { 12 | "resetContexts": false, 13 | "action": "followup.getSuggestions-more", 14 | "affectedContexts": [], 15 | "parameters": [], 16 | "messages": [], 17 | "defaultResponsePlatforms": {}, 18 | "speech": [] 19 | } 20 | ], 21 | "priority": 500000, 22 | "webhookUsed": true, 23 | "webhookForSlotFilling": false, 24 | "lastUpdate": 1508956076431, 25 | "fallbackIntent": false, 26 | "events": [] 27 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/getSuggestions - more_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "210b9f6d-89c7-471d-ae05-49b7e8f4b973", 4 | "data": [ 5 | { 6 | "text": "more", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 0 13 | }, 14 | { 15 | "id": "78dcf1d8-10f9-4fba-9bc9-a51509dec392", 16 | "data": [ 17 | { 18 | "text": "more results", 19 | "userDefined": false 20 | } 21 | ], 22 | "isTemplate": false, 23 | "count": 0, 24 | "updated": 0 25 | }, 26 | { 27 | "id": "4356d6f2-f988-4d62-9b7c-3b60f24e7f8f", 28 | "data": [ 29 | { 30 | "text": "anything else", 31 | "userDefined": false 32 | } 33 | ], 34 | "isTemplate": false, 35 | "count": 0, 36 | "updated": 0 37 | }, 38 | { 39 | "id": "0af8eeae-376c-4a2b-b439-92dae3be3148", 40 | "data": [ 41 | { 42 | "text": "other results", 43 | "userDefined": false 44 | } 45 | ], 46 | "isTemplate": false, 47 | "count": 0, 48 | "updated": 0 49 | }, 50 | { 51 | "id": "01e2680a-1cc9-43c0-9702-35d48cec066a", 52 | "data": [ 53 | { 54 | "text": "what else", 55 | "userDefined": false 56 | } 57 | ], 58 | "isTemplate": false, 59 | "count": 0, 60 | "updated": 0 61 | }, 62 | { 63 | "id": "942f06e8-ac78-43a9-b7bd-2a5235fdc66b", 64 | "data": [ 65 | { 66 | "text": "are there more", 67 | "userDefined": false 68 | } 69 | ], 70 | "isTemplate": false, 71 | "count": 0, 72 | "updated": 0 73 | }, 74 | { 75 | "id": "1434c435-3cf9-4be8-96ed-20af951d54ea", 76 | "data": [ 77 | { 78 | "text": "tell me more", 79 | "userDefined": false 80 | } 81 | ], 82 | "isTemplate": false, 83 | "count": 0, 84 | "updated": 0 85 | }, 86 | { 87 | "id": "80692ec8-d5c4-4ec2-be0a-753054ce3981", 88 | "data": [ 89 | { 90 | "text": "show me more", 91 | "userDefined": false 92 | } 93 | ], 94 | "isTemplate": false, 95 | "count": 0, 96 | "updated": 0 97 | }, 98 | { 99 | "id": "76b07453-3718-448c-b615-506af27ed56a", 100 | "data": [ 101 | { 102 | "text": "more information", 103 | "userDefined": false 104 | } 105 | ], 106 | "isTemplate": false, 107 | "count": 0, 108 | "updated": 0 109 | } 110 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/getSuggestions.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "09a1f69e-f9a5-48c6-8f9c-dc9f8a58de9b", 3 | "name": "getSuggestions", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "affectedContexts": [ 10 | { 11 | "name": "getSuggestions-followup", 12 | "parameters": {}, 13 | "lifespan": 1 14 | } 15 | ], 16 | "parameters": [], 17 | "messages": [ 18 | { 19 | "type": "simple_response", 20 | "platform": "google", 21 | "lang": "en", 22 | "items": [ 23 | { 24 | "textToSpeech": "Try commands like \"gimme some reggae bass\", \"speed this up\" or even \"try something else\" if you aren\u0027t happy with the instrument you just got." 25 | }, 26 | { 27 | "textToSpeech": "Try saying “Add a funky keyboard” or “Give me a violin”" 28 | }, 29 | { 30 | "textToSpeech": "Try saying “Give me jazz drums” or “Add a soulful piano”" 31 | }, 32 | { 33 | "textToSpeech": "Try saying “Give me a jazz bass” or “Add some funky keys”" 34 | }, 35 | { 36 | "textToSpeech": "Try saying “Give me a train whistle” or “Give me country guitar.”" 37 | }, 38 | { 39 | "textToSpeech": "Try saying “Give me a cat meow” or “Add soul guitar”" 40 | }, 41 | { 42 | "textToSpeech": "Try saying “Give me an owl hoot” or “Add funky drums”" 43 | }, 44 | { 45 | "textToSpeech": "Try saying “Give me a ghost” or “Give me polka.”" 46 | } 47 | ] 48 | } 49 | ], 50 | "defaultResponsePlatforms": {}, 51 | "speech": [] 52 | } 53 | ], 54 | "priority": 500000, 55 | "webhookUsed": false, 56 | "webhookForSlotFilling": false, 57 | "lastUpdate": 1509393490, 58 | "fallbackIntent": false, 59 | "events": [ 60 | { 61 | "name": "GET_SUGGESTIONS" 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/getSuggestions_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "f3d0f5ef-433f-477f-aec8-17d8cc380362", 4 | "data": [ 5 | { 6 | "text": "help", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 1509393464 13 | }, 14 | { 15 | "id": "bd63f786-e47d-4b21-b960-f73f30e81ad1", 16 | "data": [ 17 | { 18 | "text": "what can i play", 19 | "userDefined": false 20 | } 21 | ], 22 | "isTemplate": false, 23 | "count": 0, 24 | "updated": 1509393398 25 | }, 26 | { 27 | "id": "e41efd10-4c0c-4dcb-8de8-b8150ea7e625", 28 | "data": [ 29 | { 30 | "text": "what should i play", 31 | "userDefined": false 32 | } 33 | ], 34 | "isTemplate": false, 35 | "count": 0, 36 | "updated": 1509393398 37 | }, 38 | { 39 | "id": "44814cc0-84f4-4d9c-b9c5-648134987427", 40 | "data": [ 41 | { 42 | "text": "what can i say", 43 | "userDefined": false 44 | } 45 | ], 46 | "isTemplate": false, 47 | "count": 0, 48 | "updated": 0 49 | }, 50 | { 51 | "id": "6c5b6f03-bd35-4aa0-b1a2-64f748d3fce3", 52 | "data": [ 53 | { 54 | "text": "what else can i say", 55 | "userDefined": false 56 | } 57 | ], 58 | "isTemplate": false, 59 | "count": 1, 60 | "updated": 0 61 | }, 62 | { 63 | "id": "a21469d5-665f-4f74-aed7-8bd85efb963b", 64 | "data": [ 65 | { 66 | "text": "can you help me", 67 | "userDefined": false 68 | } 69 | ], 70 | "isTemplate": false, 71 | "count": 0, 72 | "updated": 0 73 | }, 74 | { 75 | "id": "53685c4b-a3e0-46f1-8b15-72ffa901f57c", 76 | "data": [ 77 | { 78 | "text": "what kind of suggestions do you have", 79 | "userDefined": false 80 | } 81 | ], 82 | "isTemplate": false, 83 | "count": 0, 84 | "updated": 0 85 | }, 86 | { 87 | "id": "ecec78e7-6fd8-4571-8827-dca35a823095", 88 | "data": [ 89 | { 90 | "text": "what kind of things can you do", 91 | "userDefined": false 92 | } 93 | ], 94 | "isTemplate": false, 95 | "count": 0, 96 | "updated": 0 97 | }, 98 | { 99 | "id": "e9295313-2119-4b3c-8833-40dbabc28225", 100 | "data": [ 101 | { 102 | "text": "what can you do", 103 | "userDefined": false 104 | } 105 | ], 106 | "isTemplate": false, 107 | "count": 0, 108 | "updated": 0 109 | }, 110 | { 111 | "id": "dc6265f6-3ca3-4502-84fc-542f5d269c62", 112 | "data": [ 113 | { 114 | "text": "i need help", 115 | "userDefined": false 116 | } 117 | ], 118 | "isTemplate": false, 119 | "count": 0, 120 | "updated": 0 121 | }, 122 | { 123 | "id": "e81c7389-1192-4fdc-a1d4-a42900a44bae", 124 | "data": [ 125 | { 126 | "text": "give me a suggestion", 127 | "userDefined": false 128 | } 129 | ], 130 | "isTemplate": false, 131 | "count": 0 132 | }, 133 | { 134 | "id": "2a3ae397-f09f-4cf1-8470-18d180eeaad3", 135 | "data": [ 136 | { 137 | "text": "help me", 138 | "userDefined": false 139 | } 140 | ], 141 | "isTemplate": false, 142 | "count": 0, 143 | "updated": 0 144 | }, 145 | { 146 | "id": "c7148343-0046-4fdc-8107-dd1dcee408a1", 147 | "data": [ 148 | { 149 | "text": "give me suggestions", 150 | "userDefined": false 151 | } 152 | ], 153 | "isTemplate": false, 154 | "count": 0, 155 | "updated": 0 156 | } 157 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/increaseDuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "bbb73f5f-6d08-485a-89f8-195a371d88eb", 3 | "name": "increaseDuration", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "increaseDuration", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": "simple_response", 15 | "platform": "google", 16 | "lang": "en", 17 | "customizeAudio": true, 18 | "items": [ 19 | { 20 | "textToSpeech": "$filler", 21 | "displayText": "Good idea, let\u0027s keep it going!" 22 | }, 23 | { 24 | "textToSpeech": "$filler", 25 | "displayText": "We\u0027re gonna dance all night!" 26 | } 27 | ] 28 | } 29 | ], 30 | "defaultResponsePlatforms": {}, 31 | "speech": [] 32 | } 33 | ], 34 | "priority": 500000, 35 | "webhookUsed": true, 36 | "webhookForSlotFilling": false, 37 | "lastUpdate": 1508956076238, 38 | "fallbackIntent": false, 39 | "events": [] 40 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/normalSpeed.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "60fb0ce1-0f6b-48ee-8c09-f8affbb4ffd0", 3 | "name": "normalSpeed", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "normalSpeed", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": "simple_response", 15 | "platform": "google", 16 | "lang": "en", 17 | "customizeAudio": true, 18 | "items": [ 19 | { 20 | "textToSpeech": "$filler", 21 | "displayText": "Back to normal speed." 22 | }, 23 | { 24 | "textToSpeech": "$filler", 25 | "displayText": "Aaaaand we\u0027re back to normal speed." 26 | }, 27 | { 28 | "textToSpeech": "$filler", 29 | "displayText": "Bringing it back to normal speed." 30 | } 31 | ] 32 | } 33 | ], 34 | "defaultResponsePlatforms": {}, 35 | "speech": [] 36 | } 37 | ], 38 | "priority": 500000, 39 | "webhookUsed": true, 40 | "webhookForSlotFilling": false, 41 | "lastUpdate": 1508956076183, 42 | "fallbackIntent": false, 43 | "events": [] 44 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/playAgain.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "45e539a5-b94a-4f67-be36-8f3245985fd7", 3 | "name": "playAgain", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "playAgain", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": "simple_response", 15 | "platform": "google", 16 | "lang": "en", 17 | "customizeAudio": true, 18 | "items": [ 19 | { 20 | "textToSpeech": "$filler", 21 | "displayText": "Playing again!" 22 | }, 23 | { 24 | "textToSpeech": "$filler", 25 | "displayText": "Sure, let\u0027s keep it going!" 26 | } 27 | ] 28 | } 29 | ], 30 | "defaultResponsePlatforms": {}, 31 | "speech": [] 32 | } 33 | ], 34 | "priority": 500000, 35 | "webhookUsed": true, 36 | "webhookForSlotFilling": false, 37 | "lastUpdate": 1509029336, 38 | "fallbackIntent": false, 39 | "events": [] 40 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/playAgain_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "7df1fa78-b72a-4713-8020-a93da569b97e", 4 | "data": [ 5 | { 6 | "text": "play another time", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 0 13 | }, 14 | { 15 | "id": "b7ecde23-5810-40e7-8c6c-6bedffee4bec", 16 | "data": [ 17 | { 18 | "text": "lets do that one more time", 19 | "userDefined": false 20 | } 21 | ], 22 | "isTemplate": false, 23 | "count": 0, 24 | "updated": 0 25 | }, 26 | { 27 | "id": "8225b954-7c88-4754-bc3f-f80861aa5723", 28 | "data": [ 29 | { 30 | "text": "another time", 31 | "userDefined": false 32 | } 33 | ], 34 | "isTemplate": false, 35 | "count": 0, 36 | "updated": 0 37 | }, 38 | { 39 | "id": "3df4e5a6-c3e9-4e72-af4d-40a3975f1e8c", 40 | "data": [ 41 | { 42 | "text": "i want to hear that mix again", 43 | "userDefined": false 44 | } 45 | ], 46 | "isTemplate": false, 47 | "count": 0, 48 | "updated": 0 49 | }, 50 | { 51 | "id": "b786ddfc-f32e-462f-b390-b6864f6b8505", 52 | "data": [ 53 | { 54 | "text": "lets hear that again", 55 | "userDefined": false 56 | } 57 | ], 58 | "isTemplate": false, 59 | "count": 0, 60 | "updated": 0 61 | }, 62 | { 63 | "id": "e8dc4de5-3354-4de1-bfa9-d412d55cafa5", 64 | "data": [ 65 | { 66 | "text": "play that mix again", 67 | "userDefined": false 68 | } 69 | ], 70 | "isTemplate": false, 71 | "count": 0, 72 | "updated": 0 73 | }, 74 | { 75 | "id": "054ca0c9-cb8e-4614-a150-d97fb6173f04", 76 | "data": [ 77 | { 78 | "text": "i want to hear that again", 79 | "userDefined": false 80 | } 81 | ], 82 | "isTemplate": false, 83 | "count": 0, 84 | "updated": 0 85 | }, 86 | { 87 | "id": "d19aade3-8b75-46c7-a8bb-3e60c7da68e9", 88 | "data": [ 89 | { 90 | "text": "one more time", 91 | "userDefined": false 92 | } 93 | ], 94 | "isTemplate": false, 95 | "count": 0, 96 | "updated": 0 97 | }, 98 | { 99 | "id": "1416ce36-ee06-4acc-9c2f-dfe32470cdc2", 100 | "data": [ 101 | { 102 | "text": "play again", 103 | "userDefined": false 104 | } 105 | ], 106 | "isTemplate": false, 107 | "count": 0, 108 | "updated": 0 109 | }, 110 | { 111 | "id": "91d34e1c-6172-4623-be97-1b5c76e591f6", 112 | "data": [ 113 | { 114 | "text": "repeat", 115 | "userDefined": false 116 | } 117 | ], 118 | "isTemplate": false, 119 | "count": 0, 120 | "updated": 0 121 | }, 122 | { 123 | "id": "e79888d1-69a6-4e33-bc57-f30b5afa6170", 124 | "data": [ 125 | { 126 | "text": "lets play that again", 127 | "userDefined": false 128 | } 129 | ], 130 | "isTemplate": false, 131 | "count": 0, 132 | "updated": 0 133 | } 134 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/removeInstrument.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "88d4f358-5dd9-4ee2-ae56-0d0ab1bd75c7", 3 | "name": "removeInstrument", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "removeInstrument", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "be9b86ae-69dd-4fca-9fe5-5c79bc82ae2b", 14 | "dataType": "@instrument", 15 | "name": "instrument", 16 | "value": "$instrument", 17 | "isList": false 18 | }, 19 | { 20 | "id": "8bb0cb46-4047-4ea6-bf71-3ca6aac51396", 21 | "dataType": "@genre", 22 | "name": "genre", 23 | "value": "$genre", 24 | "isList": false 25 | } 26 | ], 27 | "messages": [ 28 | { 29 | "type": "simple_response", 30 | "platform": "google", 31 | "lang": "en", 32 | "customizeAudio": true, 33 | "items": [ 34 | { 35 | "textToSpeech": "$filler", 36 | "displayText": "Removed!" 37 | }, 38 | { 39 | "textToSpeech": "$filler", 40 | "displayText": "Ok, got rid of that for you!" 41 | } 42 | ] 43 | } 44 | ], 45 | "defaultResponsePlatforms": {}, 46 | "speech": [] 47 | } 48 | ], 49 | "priority": 500000, 50 | "webhookUsed": true, 51 | "webhookForSlotFilling": false, 52 | "lastUpdate": 1509116355, 53 | "fallbackIntent": false, 54 | "events": [] 55 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/replaceInstrument.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "3308dbd4-f186-4bf6-a767-bc093094fe79", 3 | "name": "replaceInstrument", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "replaceInstrument", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "0081df0d-23c6-4cb8-aa65-2e4b4ebbeecc", 14 | "dataType": "@instrument", 15 | "name": "instrument", 16 | "value": "$instrument", 17 | "isList": false 18 | } 19 | ], 20 | "messages": [ 21 | { 22 | "type": "simple_response", 23 | "platform": "google", 24 | "lang": "en", 25 | "customizeAudio": true, 26 | "items": [ 27 | { 28 | "textToSpeech": "$filler", 29 | "displayText": "Alright, trying something different." 30 | }, 31 | { 32 | "textToSpeech": "$filler", 33 | "displayText": "Mixing it up for ya!" 34 | } 35 | ] 36 | } 37 | ], 38 | "defaultResponsePlatforms": {}, 39 | "speech": [] 40 | } 41 | ], 42 | "priority": 500000, 43 | "webhookUsed": true, 44 | "webhookForSlotFilling": false, 45 | "lastUpdate": 1508956076256, 46 | "fallbackIntent": false, 47 | "events": [] 48 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/singleInstrument.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "a715bfae-e60f-4bdd-ab33-4545ab04b0b4", 3 | "name": "singleInstrument", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "singleInstrument", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "dbe0f375-0c7f-49f7-9b2a-85dd4a3fe8c0", 14 | "required": true, 15 | "dataType": "@instrument", 16 | "name": "instrument", 17 | "value": "$instrument", 18 | "prompts": [ 19 | { 20 | "lang": "en", 21 | "value": "Ok, which instrument do you want to keep?" 22 | } 23 | ], 24 | "isList": false 25 | }, 26 | { 27 | "id": "dd5ed065-f40a-4695-aba9-11a19d3806cf", 28 | "dataType": "@genre", 29 | "name": "genre", 30 | "value": "$genre", 31 | "isList": false 32 | } 33 | ], 34 | "messages": [ 35 | { 36 | "type": "simple_response", 37 | "platform": "google", 38 | "lang": "en", 39 | "customizeAudio": true, 40 | "items": [ 41 | { 42 | "textToSpeech": "$filler", 43 | "displayText": "Ok, we solo\u0027d that for you." 44 | }, 45 | { 46 | "textToSpeech": "$filler", 47 | "displayText": "Great, back to a single instrument." 48 | } 49 | ] 50 | } 51 | ], 52 | "defaultResponsePlatforms": {}, 53 | "speech": [] 54 | } 55 | ], 56 | "priority": 500000, 57 | "webhookUsed": true, 58 | "webhookForSlotFilling": false, 59 | "lastUpdate": 1508956076226, 60 | "fallbackIntent": false, 61 | "events": [] 62 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/slowDown.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2ac7127f-d397-4d3f-b7e4-40f30018e9ec", 3 | "name": "slowDown", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "slowDown", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "4fa4eb6c-b623-4cd3-901c-349151ecd4f3", 14 | "dataType": "@sys.percentage", 15 | "name": "percentage", 16 | "value": "$percentage", 17 | "isList": false 18 | } 19 | ], 20 | "messages": [ 21 | { 22 | "type": "simple_response", 23 | "platform": "google", 24 | "lang": "en", 25 | "customizeAudio": true, 26 | "items": [ 27 | { 28 | "textToSpeech": "$filler", 29 | "displayText": "Ok, that\u0027s a bit slower." 30 | }, 31 | { 32 | "textToSpeech": "$filler", 33 | "displayText": "Slowwwww dowwwwwwn." 34 | } 35 | ] 36 | } 37 | ], 38 | "defaultResponsePlatforms": {}, 39 | "speech": [] 40 | } 41 | ], 42 | "priority": 500000, 43 | "webhookUsed": true, 44 | "webhookForSlotFilling": false, 45 | "lastUpdate": 1508956076231, 46 | "fallbackIntent": false, 47 | "events": [] 48 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/slowDown_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "28029672-6fd6-4980-8c1e-b59746016ebf", 4 | "data": [ 5 | { 6 | "text": "slow down", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 0 13 | }, 14 | { 15 | "id": "49c88b49-6cae-4c27-a692-e60b29f9efa1", 16 | "data": [ 17 | { 18 | "text": "15%", 19 | "alias": "percentage", 20 | "meta": "@sys.percentage", 21 | "userDefined": false 22 | }, 23 | { 24 | "text": " slower", 25 | "userDefined": false 26 | } 27 | ], 28 | "isTemplate": false, 29 | "count": 0, 30 | "updated": 0 31 | }, 32 | { 33 | "id": "ce3c6113-6cde-4f11-b6a1-47f0f319087b", 34 | "data": [ 35 | { 36 | "text": "slow it down by ", 37 | "userDefined": false 38 | }, 39 | { 40 | "text": "15%", 41 | "alias": "percentage", 42 | "meta": "@sys.percentage", 43 | "userDefined": false 44 | } 45 | ], 46 | "isTemplate": false, 47 | "count": 0, 48 | "updated": 0 49 | }, 50 | { 51 | "id": "151803db-1be7-4315-a61d-68421b71d742", 52 | "data": [ 53 | { 54 | "text": "slow it down ", 55 | "userDefined": false 56 | }, 57 | { 58 | "text": "15%", 59 | "alias": "percentage", 60 | "meta": "@sys.percentage", 61 | "userDefined": false 62 | } 63 | ], 64 | "isTemplate": false, 65 | "count": 0, 66 | "updated": 0 67 | }, 68 | { 69 | "id": "65819d39-e2bf-408a-b3c3-1936db3396b4", 70 | "data": [ 71 | { 72 | "text": "make it ", 73 | "userDefined": false 74 | }, 75 | { 76 | "text": "15%", 77 | "alias": "percentage", 78 | "meta": "@sys.percentage", 79 | "userDefined": false 80 | }, 81 | { 82 | "text": " slower", 83 | "userDefined": false 84 | } 85 | ], 86 | "isTemplate": false, 87 | "count": 0, 88 | "updated": 0 89 | }, 90 | { 91 | "id": "4f9575eb-103a-4f7a-b454-248d2f7f16e6", 92 | "data": [ 93 | { 94 | "text": "reduce speed", 95 | "userDefined": false 96 | } 97 | ], 98 | "isTemplate": false, 99 | "count": 0, 100 | "updated": 0 101 | }, 102 | { 103 | "id": "bcaf76da-f85f-4d39-a032-7ca0ea505eb4", 104 | "data": [ 105 | { 106 | "text": "slow it down", 107 | "userDefined": false 108 | } 109 | ], 110 | "isTemplate": false, 111 | "count": 0, 112 | "updated": 0 113 | }, 114 | { 115 | "id": "290592ab-5e6e-40a5-be7f-46835fca0c1b", 116 | "data": [ 117 | { 118 | "text": "maker it slower", 119 | "userDefined": false 120 | } 121 | ], 122 | "isTemplate": false, 123 | "count": 0, 124 | "updated": 0 125 | } 126 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/speedUp.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c7264473-cafa-4a7d-b2e3-f50db2d0fb59", 3 | "name": "speedUp", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "speedUp", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "9195e0ab-671b-44aa-a7e6-0a4d967530ce", 14 | "dataType": "@sys.percentage", 15 | "name": "percentage", 16 | "value": "$percentage", 17 | "isList": false 18 | } 19 | ], 20 | "messages": [ 21 | { 22 | "type": "simple_response", 23 | "platform": "google", 24 | "lang": "en", 25 | "customizeAudio": true, 26 | "items": [ 27 | { 28 | "textToSpeech": "$filler", 29 | "displayText": "Ok! Let\u0027s kick it up a notch." 30 | }, 31 | { 32 | "textToSpeech": "$filler", 33 | "displayText": "Here we go!" 34 | } 35 | ] 36 | } 37 | ], 38 | "defaultResponsePlatforms": {}, 39 | "speech": [] 40 | } 41 | ], 42 | "priority": 500000, 43 | "webhookUsed": true, 44 | "webhookForSlotFilling": false, 45 | "lastUpdate": 1508956076199, 46 | "fallbackIntent": false, 47 | "events": [] 48 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/superFast.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "48a90a9d-16bc-4979-aa6b-a4eae1b56788", 3 | "name": "superFast", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "superFast", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": "simple_response", 15 | "platform": "google", 16 | "lang": "en", 17 | "customizeAudio": true, 18 | "items": [ 19 | { 20 | "textToSpeech": "$filler", 21 | "displayText": "Hyperspeed, ENGAGED!" 22 | }, 23 | { 24 | "textToSpeech": "$filler", 25 | "displayText": "LET\u0027S GOOOOOOOO" 26 | } 27 | ] 28 | } 29 | ], 30 | "defaultResponsePlatforms": {}, 31 | "speech": [] 32 | } 33 | ], 34 | "priority": 500000, 35 | "webhookUsed": true, 36 | "webhookForSlotFilling": false, 37 | "lastUpdate": 1508956076177, 38 | "fallbackIntent": false, 39 | "events": [] 40 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/superFast_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "76caf848-f9d4-4cec-bddd-e13bcef5676d", 4 | "data": [ 5 | { 6 | "text": "make it super fast", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 1507753149 13 | }, 14 | { 15 | "id": "c9f64eca-34c0-4f60-9f42-3013e5bc3c68", 16 | "data": [ 17 | { 18 | "text": "make it epic ", 19 | "userDefined": false 20 | }, 21 | { 22 | "text": "fast", 23 | "meta": "@sys.ignore", 24 | "userDefined": false 25 | } 26 | ], 27 | "isTemplate": false, 28 | "count": 0, 29 | "updated": 1507753149 30 | }, 31 | { 32 | "id": "b15fe24e-d445-41df-879d-29e6395e1b0d", 33 | "data": [ 34 | { 35 | "text": "make super ", 36 | "userDefined": false 37 | }, 38 | { 39 | "text": "fast", 40 | "meta": "@sys.ignore", 41 | "userDefined": false 42 | } 43 | ], 44 | "isTemplate": false, 45 | "count": 0, 46 | "updated": 1507753149 47 | }, 48 | { 49 | "id": "fa6a9eb0-9c93-4305-9088-1a35a26b2d0f", 50 | "data": [ 51 | { 52 | "text": "max speed", 53 | "userDefined": false 54 | } 55 | ], 56 | "isTemplate": false, 57 | "count": 0, 58 | "updated": 1507753149 59 | }, 60 | { 61 | "id": "d0cedf75-7a48-45a1-83b1-9f46d68c414d", 62 | "data": [ 63 | { 64 | "text": "as fast as you can", 65 | "userDefined": false 66 | } 67 | ], 68 | "isTemplate": false, 69 | "count": 0, 70 | "updated": 1507753149 71 | }, 72 | { 73 | "id": "ea520179-ebb6-46f3-93c7-3fe6e0adf8c1", 74 | "data": [ 75 | { 76 | "text": "as fast as possible", 77 | "userDefined": false 78 | } 79 | ], 80 | "isTemplate": false, 81 | "count": 0, 82 | "updated": 1507753149 83 | }, 84 | { 85 | "id": "a40bac95-1d11-4f16-90ce-3215984423ce", 86 | "data": [ 87 | { 88 | "text": "make it as fast as you can", 89 | "userDefined": false 90 | } 91 | ], 92 | "isTemplate": false, 93 | "count": 0, 94 | "updated": 1507753149 95 | }, 96 | { 97 | "id": "899f0eee-b0c9-4ac0-b062-1fb830b6e3c7", 98 | "data": [ 99 | { 100 | "text": "make it faster than fast", 101 | "userDefined": false 102 | } 103 | ], 104 | "isTemplate": false, 105 | "count": 0, 106 | "updated": 1507753149 107 | }, 108 | { 109 | "id": "c45f55b6-62ac-401d-81f7-3cb82d6b301d", 110 | "data": [ 111 | { 112 | "text": "make it ", 113 | "userDefined": false 114 | }, 115 | { 116 | "text": "crazy", 117 | "meta": "@sys.ignore", 118 | "userDefined": false 119 | }, 120 | { 121 | "text": " fast", 122 | "userDefined": false 123 | } 124 | ], 125 | "isTemplate": false, 126 | "count": 1, 127 | "updated": 1507753149 128 | }, 129 | { 130 | "id": "0d382ba2-1ab5-4bca-b8b3-116dae041509", 131 | "data": [ 132 | { 133 | "text": "speed it way up", 134 | "userDefined": false 135 | } 136 | ], 137 | "isTemplate": false, 138 | "count": 0, 139 | "updated": 1507753149 140 | } 141 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/superSlow.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "ed2d91ac-d912-4637-8049-050ee76cb2a7", 3 | "name": "superSlow", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "superSlow", 10 | "affectedContexts": [], 11 | "parameters": [], 12 | "messages": [ 13 | { 14 | "type": "simple_response", 15 | "platform": "google", 16 | "lang": "en", 17 | "customizeAudio": true, 18 | "items": [ 19 | { 20 | "textToSpeech": "$filler", 21 | "displayText": "Slow enough for ya?" 22 | }, 23 | { 24 | "textToSpeech": "$filler", 25 | "displayText": "...are you a turtle?" 26 | } 27 | ] 28 | } 29 | ], 30 | "defaultResponsePlatforms": {}, 31 | "speech": [] 32 | } 33 | ], 34 | "priority": 500000, 35 | "webhookUsed": true, 36 | "webhookForSlotFilling": false, 37 | "lastUpdate": 1508956076216, 38 | "fallbackIntent": false, 39 | "events": [] 40 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/superSlow_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "aeaa9460-212b-4225-999b-d642cf25854b", 4 | "data": [ 5 | { 6 | "text": "slow it all the way down", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 0 13 | }, 14 | { 15 | "id": "88199bcd-adce-4379-8079-e75c2b817e9f", 16 | "data": [ 17 | { 18 | "text": "make it as slow as possible", 19 | "userDefined": false 20 | } 21 | ], 22 | "isTemplate": false, 23 | "count": 0, 24 | "updated": 0 25 | }, 26 | { 27 | "id": "ad9a3b18-67c1-40c8-a1ee-d489e6152cc0", 28 | "data": [ 29 | { 30 | "text": "make it as slow as you can", 31 | "userDefined": false 32 | } 33 | ], 34 | "isTemplate": false, 35 | "count": 0, 36 | "updated": 0 37 | }, 38 | { 39 | "id": "02f47599-76fe-4efc-9fec-5f4739ef91ee", 40 | "data": [ 41 | { 42 | "text": "make it slower than slow", 43 | "userDefined": false 44 | } 45 | ], 46 | "isTemplate": false, 47 | "count": 0, 48 | "updated": 0 49 | }, 50 | { 51 | "id": "15a70925-442a-488e-afbe-264a98f9f991", 52 | "data": [ 53 | { 54 | "text": "make it really slow", 55 | "userDefined": false 56 | } 57 | ], 58 | "isTemplate": false, 59 | "count": 0, 60 | "updated": 0 61 | }, 62 | { 63 | "id": "858895b1-9010-44f4-81be-4f7f0aa29d21", 64 | "data": [ 65 | { 66 | "text": "make it super slow", 67 | "userDefined": false 68 | } 69 | ], 70 | "isTemplate": false, 71 | "count": 0, 72 | "updated": 0 73 | } 74 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/volumeDown.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "b2b13011-ec3f-4c88-9499-820f389c2a15", 3 | "name": "volumeDown", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "volumeDown", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "a53b0d78-10aa-445c-89cd-4b1275092ec4", 14 | "dataType": "@instrument", 15 | "name": "instrument", 16 | "value": "$instrument", 17 | "isList": false 18 | } 19 | ], 20 | "messages": [ 21 | { 22 | "type": "simple_response", 23 | "platform": "google", 24 | "lang": "en", 25 | "customizeAudio": true, 26 | "items": [ 27 | { 28 | "textToSpeech": "$filler", 29 | "displayText": "Turning it down." 30 | }, 31 | { 32 | "textToSpeech": "$filler", 33 | "displayText": "Bringing the volume down." 34 | } 35 | ] 36 | } 37 | ], 38 | "defaultResponsePlatforms": {}, 39 | "speech": [] 40 | } 41 | ], 42 | "priority": 500000, 43 | "webhookUsed": true, 44 | "webhookForSlotFilling": false, 45 | "lastUpdate": 1509116549, 46 | "fallbackIntent": false, 47 | "events": [] 48 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/volumeUp.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1d8a737f-2fa4-4395-bcc0-bdf28823677f", 3 | "name": "volumeUp", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "volumeUp", 10 | "affectedContexts": [], 11 | "parameters": [ 12 | { 13 | "id": "1c4b2789-4555-4351-a665-503fecd8bc84", 14 | "required": false, 15 | "dataType": "@instrument", 16 | "name": "instrument", 17 | "value": "$instrument", 18 | "isList": false 19 | } 20 | ], 21 | "messages": [ 22 | { 23 | "type": "simple_response", 24 | "platform": "google", 25 | "lang": "en", 26 | "customizeAudio": true, 27 | "items": [ 28 | { 29 | "textToSpeech": "$filler", 30 | "displayText": "Cranking it up." 31 | }, 32 | { 33 | "textToSpeech": "$filler", 34 | "displayText": "Turning the volume up." 35 | }, 36 | { 37 | "textToSpeech": "$filler", 38 | "displayText": "Going up to 11." 39 | } 40 | ] 41 | } 42 | ], 43 | "defaultResponsePlatforms": {}, 44 | "speech": [] 45 | } 46 | ], 47 | "priority": 500000, 48 | "webhookUsed": true, 49 | "webhookForSlotFilling": false, 50 | "lastUpdate": 1509116745, 51 | "fallbackIntent": false, 52 | "events": [] 53 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/welcome - no.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "935c8a34-7e4e-4719-89d2-7614dfef8ff4", 3 | "parentId": "33c57714-c77a-4686-a7c7-16d5fbf9d314", 4 | "rootParentId": "33c57714-c77a-4686-a7c7-16d5fbf9d314", 5 | "name": "welcome - no", 6 | "auto": true, 7 | "contexts": [ 8 | "welcome-followup" 9 | ], 10 | "responses": [ 11 | { 12 | "resetContexts": false, 13 | "action": "welcome.welcome-no", 14 | "affectedContexts": [], 15 | "parameters": [], 16 | "messages": [ 17 | { 18 | "type": "simple_response", 19 | "platform": "google", 20 | "lang": "en", 21 | "customizeAudio": true, 22 | "textToSpeech": "Awesome. Just say “Ok Google, what should I play” if you need help. How do you want to kick it off?", 23 | "displayText": "Awesome. Just say “Ok Google, what should I play” if you need help. How do you want to kick it off?" 24 | } 25 | ], 26 | "defaultResponsePlatforms": {}, 27 | "speech": [] 28 | } 29 | ], 30 | "priority": 500000, 31 | "webhookUsed": false, 32 | "webhookForSlotFilling": false, 33 | "lastUpdate": 1509393372, 34 | "fallbackIntent": false, 35 | "events": [] 36 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/welcome - yes.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "db4e37d4-4741-407c-955e-d6a63f454c46", 3 | "parentId": "33c57714-c77a-4686-a7c7-16d5fbf9d314", 4 | "rootParentId": "33c57714-c77a-4686-a7c7-16d5fbf9d314", 5 | "name": "welcome - yes", 6 | "auto": true, 7 | "contexts": [ 8 | "welcome-followup" 9 | ], 10 | "responses": [ 11 | { 12 | "resetContexts": false, 13 | "action": "welcome.welcome-yes", 14 | "affectedContexts": [], 15 | "parameters": [], 16 | "messages": [ 17 | { 18 | "type": "simple_response", 19 | "platform": "google", 20 | "lang": "en", 21 | "customizeAudio": true, 22 | "textToSpeech": "We’re going to make music using your voice commands. To add a track to your mix, say something like “Ok Google, add a funky beat” or “Hey Google, give me a happy guitar.” Feel free to hit me up for suggestions at any time. If you’re ready, let’s start jamming.", 23 | "displayText": "We’re going to make music using your voice commands. To add a track to your mix, say something like “Ok Google, add a funky beat” or “Hey Google, give me a happy guitar.” Feel free to hit me up for suggestions at any time. If you’re ready, let’s start jamming." 24 | } 25 | ], 26 | "defaultResponsePlatforms": {}, 27 | "speech": [] 28 | } 29 | ], 30 | "priority": 500000, 31 | "webhookUsed": false, 32 | "webhookForSlotFilling": false, 33 | "lastUpdate": 1509393449, 34 | "fallbackIntent": false, 35 | "events": [] 36 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/welcome - yes_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "b5ed7f45-50c7-4591-a562-d39c186fa977", 4 | "data": [ 5 | { 6 | "text": "yep", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 1507087242 13 | }, 14 | { 15 | "id": "67813b4a-6a6b-4be7-8e99-78b48d9c1525", 16 | "data": [ 17 | { 18 | "text": "yup", 19 | "userDefined": false 20 | } 21 | ], 22 | "isTemplate": false, 23 | "count": 0, 24 | "updated": 1507087242 25 | }, 26 | { 27 | "id": "4c1264e3-4ccd-42c6-a7cc-75556136fb3f", 28 | "data": [ 29 | { 30 | "text": "ok", 31 | "userDefined": false 32 | } 33 | ], 34 | "isTemplate": false, 35 | "count": 0, 36 | "updated": 0 37 | }, 38 | { 39 | "id": "60318e5a-1523-4c59-9d2b-e669c63a327b", 40 | "data": [ 41 | { 42 | "text": "okay", 43 | "userDefined": false 44 | } 45 | ], 46 | "isTemplate": false, 47 | "count": 0, 48 | "updated": 0 49 | }, 50 | { 51 | "id": "ec08c842-e91a-4c06-b7dd-a2cc41adc03c", 52 | "data": [ 53 | { 54 | "text": "yes", 55 | "userDefined": false 56 | } 57 | ], 58 | "isTemplate": false, 59 | "count": 0, 60 | "updated": 0 61 | }, 62 | { 63 | "id": "fb487e17-cf7f-4ddd-8e36-35cea977ad08", 64 | "data": [ 65 | { 66 | "text": "do it", 67 | "userDefined": false 68 | } 69 | ], 70 | "isTemplate": false, 71 | "count": 1, 72 | "updated": 0 73 | }, 74 | { 75 | "id": "655fc0b6-48bf-4bbb-b878-fe3a4ca23c84", 76 | "data": [ 77 | { 78 | "text": "sure", 79 | "userDefined": false 80 | } 81 | ], 82 | "isTemplate": false, 83 | "count": 2, 84 | "updated": 0 85 | }, 86 | { 87 | "id": "2f7a8627-b1a1-46bb-92de-f6c7411def1a", 88 | "data": [ 89 | { 90 | "text": "exactly", 91 | "userDefined": false 92 | } 93 | ], 94 | "isTemplate": false, 95 | "count": 0, 96 | "updated": 0 97 | }, 98 | { 99 | "id": "b767efaf-3321-4dfd-98ac-f1533e7cc078", 100 | "data": [ 101 | { 102 | "text": "confirm", 103 | "userDefined": false 104 | } 105 | ], 106 | "isTemplate": false, 107 | "count": 1, 108 | "updated": 0 109 | }, 110 | { 111 | "id": "9867257c-149f-434c-908c-7e7b6c763155", 112 | "data": [ 113 | { 114 | "text": "of course", 115 | "userDefined": false 116 | } 117 | ], 118 | "isTemplate": false, 119 | "count": 0, 120 | "updated": 0 121 | }, 122 | { 123 | "id": "c84b50d7-bf7e-45cb-93e1-a1b86c50efae", 124 | "data": [ 125 | { 126 | "text": "sounds good", 127 | "userDefined": false 128 | } 129 | ], 130 | "isTemplate": false, 131 | "count": 0, 132 | "updated": 0 133 | }, 134 | { 135 | "id": "ebf9150a-d882-481c-8c0b-4679b29b2eab", 136 | "data": [ 137 | { 138 | "text": "that\u0027s correct", 139 | "userDefined": false 140 | } 141 | ], 142 | "isTemplate": false, 143 | "count": 0, 144 | "updated": 0 145 | }, 146 | { 147 | "id": "434d0f43-f5f6-4953-8afc-c87236ed6490", 148 | "data": [ 149 | { 150 | "text": "I don\u0027t mind", 151 | "userDefined": false 152 | } 153 | ], 154 | "isTemplate": false, 155 | "count": 0, 156 | "updated": 0 157 | }, 158 | { 159 | "id": "7ff4084a-540f-4049-98f8-427118717f2a", 160 | "data": [ 161 | { 162 | "text": "I agree", 163 | "userDefined": false 164 | } 165 | ], 166 | "isTemplate": false, 167 | "count": 1, 168 | "updated": 0 169 | } 170 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/welcome.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "33c57714-c77a-4686-a7c7-16d5fbf9d314", 3 | "name": "welcome", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "action": "welcome", 10 | "affectedContexts": [ 11 | { 12 | "name": "welcome-followup", 13 | "parameters": {}, 14 | "lifespan": 1 15 | } 16 | ], 17 | "parameters": [], 18 | "messages": [ 19 | { 20 | "type": "simple_response", 21 | "platform": "google", 22 | "lang": "en", 23 | "customizeAudio": true, 24 | "items": [ 25 | { 26 | "textToSpeech": "Welcome to Mix Lab. Is this your first time here?", 27 | "displayText": "Welcome to Mix Lab. Is this your first time here?" 28 | }, 29 | { 30 | "textToSpeech": "Welcome to Mix Lab. Is this your first time jamming?", 31 | "displayText": "Welcome to Mix Lab. Is this your first time jamming?" 32 | }, 33 | { 34 | "textToSpeech": "Welcome to Mix Lab. Is this your first time making a mix?", 35 | "displayText": "Welcome to Mix Lab. Is this your first time making a mix?" 36 | } 37 | ] 38 | } 39 | ], 40 | "defaultResponsePlatforms": {}, 41 | "speech": [] 42 | } 43 | ], 44 | "priority": 500000, 45 | "webhookUsed": true, 46 | "webhookForSlotFilling": false, 47 | "lastUpdate": 1508956076264, 48 | "fallbackIntent": false, 49 | "events": [ 50 | { 51 | "name": "GOOGLE_ASSISTANT_WELCOME" 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/whoMadeDis.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "7c0136e0-6f1e-4b85-86b7-e86878aa8a43", 3 | "name": "whoMadeDis", 4 | "auto": true, 5 | "contexts": [], 6 | "responses": [ 7 | { 8 | "resetContexts": false, 9 | "affectedContexts": [], 10 | "parameters": [], 11 | "messages": [ 12 | { 13 | "type": "simple_response", 14 | "platform": "google", 15 | "lang": "en", 16 | "customizeAudio": true, 17 | "textToSpeech": "Mix Lab was made by Google Creative Lab. Music direction was provided by Blake Strauss. Find out more at g.co/mixlab.", 18 | "displayText": "Mix Lab was made by Google Creative Lab. Music direction was provided by Blake Strauss. Find out more at g.co/mixlab." 19 | } 20 | ], 21 | "defaultResponsePlatforms": {}, 22 | "speech": [] 23 | } 24 | ], 25 | "priority": 500000, 26 | "webhookUsed": false, 27 | "webhookForSlotFilling": false, 28 | "lastUpdate": 1509393922062, 29 | "fallbackIntent": false, 30 | "events": [] 31 | } -------------------------------------------------------------------------------- /dialogflow/mixlab/intents/whoMadeDis_usersays_en.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "28e52d34-42a7-451b-8ebf-047336142d34", 4 | "data": [ 5 | { 6 | "text": "who made you?", 7 | "userDefined": false 8 | } 9 | ], 10 | "isTemplate": false, 11 | "count": 0, 12 | "updated": 0 13 | }, 14 | { 15 | "id": "d6417ad1-960b-4130-994e-3c9b017ef071", 16 | "data": [ 17 | { 18 | "text": "who made this?", 19 | "userDefined": false 20 | } 21 | ], 22 | "isTemplate": false, 23 | "count": 0, 24 | "updated": 0 25 | } 26 | ] -------------------------------------------------------------------------------- /dialogflow/mixlab/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0" 3 | } -------------------------------------------------------------------------------- /images/mixlab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/images/mixlab.jpg -------------------------------------------------------------------------------- /webhook/cors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "origin": ["https://your-app.appspot.com", "http://localhost:5000"], 4 | "responseHeader": ["Content-Type"], 5 | "method": ["GET"], 6 | "maxAgeSeconds": 3600 7 | } 8 | ] -------------------------------------------------------------------------------- /webhook/firebasedatabase.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Google Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | "use strict"; 17 | 18 | const serviceAccount = require("./firebase_credentials.json"); 19 | const admin = require("firebase-admin"); 20 | 21 | // set up firebase config 22 | class FirebaseDatabase { 23 | constructor() { 24 | this.config = { 25 | credential: admin.credential.cert(serviceAccount), 26 | databaseURL: "https://say-to-play.firebaseio.com/" 27 | }; 28 | 29 | this.initialize() 30 | } 31 | 32 | initialize() { 33 | if (!admin.apps.length) { 34 | admin.initializeApp(this.config); 35 | } 36 | this.ref = admin.database().ref(); 37 | this.errorsRef = this.ref.child("errors"); 38 | this.logsRef = this.ref.child("logs"); 39 | } 40 | 41 | // Log errors from fallback intent 42 | error(sessionId, category, label = "", action = "Intent") { 43 | this.currentSessionRef = this.errorsRef.child(sessionId); 44 | const data = { 45 | category: category, 46 | action: action, 47 | label: label 48 | }; 49 | this.currentSessionRef.push(data); 50 | } 51 | 52 | log(sessionId, category, data = null) { 53 | this.currentSessionRef = this.logsRef.child(sessionId); 54 | 55 | const dataToLog = { 56 | category: category, 57 | action: "Intent" 58 | } 59 | 60 | if(data !== null) { 61 | dataToLog['data'] = data 62 | } 63 | 64 | this.currentSessionRef.push(dataToLog); 65 | } 66 | } 67 | 68 | exports.firebaseDB = new FirebaseDatabase() 69 | -------------------------------------------------------------------------------- /webhook/followups.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict' 18 | 19 | const ACTION_SUGGESTIONS_FOLLOWUP = 'followup.getSuggestions-more' 20 | 21 | const EVENT_GET_SUGGESTIONS = "GET_SUGGESTIONS" 22 | 23 | exports.handleFollowups = (app, reqBody, res) => { 24 | let action = app.getIntent() 25 | switch(action) { 26 | case ACTION_SUGGESTIONS_FOLLOWUP: 27 | return handleSuggestionFollowup(res) 28 | } 29 | } 30 | 31 | 32 | const handleSuggestionFollowup = res => { 33 | let data = { 34 | followupEvent: { 35 | name: EVENT_GET_SUGGESTIONS 36 | } 37 | } 38 | 39 | res.setHeader('Content-Type', 'application/json'); 40 | res.send( 41 | JSON.stringify(data) 42 | ) 43 | } -------------------------------------------------------------------------------- /webhook/logging.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict' 18 | 19 | const IS_DEBUG = true 20 | 21 | /** 22 | * Use this logging for development purposes, as it will be disabled once we push live. 23 | * 24 | * @param args just like any other console.log(...) message. 25 | */ 26 | exports.logDebug = (...args) => { 27 | if(IS_DEBUG) { 28 | console.log.apply(this, args); 29 | } 30 | } 31 | 32 | /** 33 | * log all fallback and breaking errors here, with fallback mostly used for updating synonyms 34 | * 35 | * @param args Preferred to use format logError(functionName|tag, ...errors) - this will help with filtering 36 | */ 37 | exports.logError = (...args) => { 38 | console.error.apply(this, args); 39 | } 40 | 41 | /** 42 | * Use this logging for all 'analytic'-style events. For easier searching later, additional tag is required. 43 | * 44 | * @param tag Tag used for filtering in searches 45 | * @param args 46 | */ 47 | exports.log = (tag, ...args) => { 48 | let arr = Array.prototype.slice.call(args) 49 | arr.unshift(tag + " ") 50 | console.log.apply(this, arr) 51 | } -------------------------------------------------------------------------------- /webhook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MixLab", 3 | "description": "A Voice Experiment that gives users the ability to make music just by telling the app what they want to hear.", 4 | "version": "1.0.0", 5 | "license": "Apache Version 2.0", 6 | "author": "Google Creative Lab & Friends", 7 | "scripts": { 8 | "lint": "eslint --fix \"**/*.js\"", 9 | "deploy": "gcloud beta functions deploy webhook --trigger-http --stage-bucket staging.say-to-play.appspot.com", 10 | "stage": "gcloud beta functions deploy webhookStaging --trigger-http --stage-bucket staging.say-to-play.appspot.com", 11 | "call": "gcloud beta functions call webhook", 12 | "test": "functions call webhook --file=test-data.json && functions logs read" 13 | }, 14 | "dependencies": { 15 | "@google-cloud/datastore": "^1.1.0", 16 | "actions-on-google": "^1.5.1", 17 | "firebase-admin": "^5.5.0", 18 | "node-fetch": "^1.7.3", 19 | "superagent": "^3.8.1" 20 | }, 21 | "devDependencies": { 22 | "eslint": "^4.11.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /webhook/sharing-card.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict' 18 | 19 | const CARD_TITLE = 'Mix Lab'; 20 | const CARD_SUBTITLE = 'Make music using simple voice commands.'; 21 | const CARD_BODY = 'Tap here to keep this jam going in a web browser.' 22 | const CARD_IMAGE_URL = 'https://lh3.googleusercontent.com/-CZ4syu3crCg/WdJrKk1v3xI/AAAAAAAAAe0/rhx3JcZTHnYYyO0iILI5CpY0ZlEWNicbwCMYCGAYYCw/h1080-w1920/MixLab_1920x1080%2B%25281%2529.png'; 23 | const CARD_IMAGE_ACCESS = 'Mix Lab Website Screenshot'; 24 | const CARD_BUTTON_TEXT = 'Mix Lab Web Experience'; 25 | const CARD_SITE_URL = 'https://mixlab.withgoogle.com/jam/'; 26 | 27 | const makeCard = (app, shareId = '') => { 28 | let buttonUrl = CARD_SITE_URL + shareId 29 | 30 | return app.buildBasicCard(CARD_BODY) 31 | .setTitle(CARD_TITLE) 32 | .setSubtitle(CARD_SUBTITLE) 33 | .setImage(CARD_IMAGE_URL, CARD_IMAGE_ACCESS) 34 | .addButton(CARD_BUTTON_TEXT, buttonUrl) 35 | } 36 | 37 | exports.makeCard = makeCard -------------------------------------------------------------------------------- /webhook/simple-actions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict' 18 | 19 | const ChirpSessionManager = require('./chirp-session-manager') 20 | 21 | const response = require('./response') 22 | 23 | const { logDebug } = require('./logging') 24 | 25 | const DURATION_INCR = ChirpSessionManager.DEFAULT_DURATION // for now 26 | const DURATION_MAX = ChirpSessionManager.DEFAULT_DURATION + (DURATION_INCR * 6) 27 | 28 | exports.clearSession = (app, currentSession, sessionId) => { 29 | if(currentSession.stems.length === 0) { 30 | return response.makeClearResponse(app, true) 31 | } 32 | 33 | ChirpSessionManager.clearSession(sessionId, currentSession) 34 | .then(entity => { 35 | return response.makeClearResponse(app) 36 | }) 37 | .catch(err => { 38 | return app.ask('Sorry, I\'m broken, try again.') 39 | }) 40 | } 41 | 42 | exports.playSingleInstrument = (app, currentSession, sessionId) => { 43 | //instrument is required so grab it 44 | let instrument = app.getArgument('instrument') 45 | let stemToKeep = null 46 | 47 | for(let i = 0; i < currentSession.stems.length; i++) { 48 | let stem = currentSession.stems[i] 49 | 50 | if(stem.instrument === instrument || 51 | stem.instrumentCategory === instrument) { 52 | stemToKeep = stem 53 | break 54 | } 55 | } 56 | 57 | if(!stemToKeep) { 58 | return app.ask("You can't keep something you don't have, please try again.") 59 | } 60 | 61 | currentSession.stems = [stemToKeep] 62 | 63 | ChirpSessionManager.updateSession(sessionId, currentSession, app) 64 | .then(entity => response.makeAudioResponse(app, currentSession)) 65 | } 66 | 67 | exports.increaseDuration = (app, currentSession, sessionId) => { 68 | if(currentSession.stems.length === 0) { 69 | return response.makeCantIncreaseDurationResponse(app) 70 | } 71 | 72 | let newDuration = currentSession[ChirpSessionManager.PROP_DURATION] + DURATION_INCR 73 | if(newDuration > DURATION_MAX) { 74 | newDuration = DURATION_MAX 75 | } 76 | 77 | currentSession[ChirpSessionManager.PROP_DURATION] = newDuration 78 | 79 | ChirpSessionManager.updateSession(sessionId, currentSession, app) 80 | .then(entity => response.makeAudioResponse(app, currentSession)) 81 | } 82 | 83 | exports.playAgain = (app, currentSession, sessionId) => { 84 | if(currentSession.stems.length === 0) { 85 | return response.makePlayWhatAgainResponse(app) 86 | } 87 | 88 | // just do it again! 89 | response.makeAudioResponse(app, currentSession) 90 | } -------------------------------------------------------------------------------- /webhook/test-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "f4abdf5f-5c72-4e94-89a9-93b4bb93d740", 3 | "timestamp": "2017-09-11T21:06:15.103Z", 4 | "lang": "en", 5 | "result": { 6 | "source": "agent", 7 | "resolvedQuery": "add a funky electric guitar", 8 | "action": "addInstrument", 9 | "actionIncomplete": false, 10 | "parameters": { 11 | "genre": "Funk", 12 | "instrument": "Guitar", 13 | "wildcard": "" 14 | }, 15 | "contexts": [ 16 | { 17 | "name": "_actions_on_google_", 18 | "parameters": { 19 | "genre": "Funk", 20 | "wildcard.original": "", 21 | "instrument": "Guitar", 22 | "instrument.original": "electric guitar", 23 | "genre.original": "funky", 24 | "wildcard": "" 25 | }, 26 | "lifespan": 100 27 | } 28 | ], 29 | "metadata": { 30 | "intentId": "334d2ac5-b715-459b-9153-c3708623c971", 31 | "webhookUsed": "true", 32 | "webhookForSlotFillingUsed": "false", 33 | "webhookResponseTime": 394, 34 | "intentName": "addInstrument" 35 | }, 36 | "fulfillment": { 37 | "speech": "Thank you for testing add instrument. What next?", 38 | "messages": [ 39 | { 40 | "type": 0, 41 | "speech": "Thank you for testing add instrument. What next?" 42 | } 43 | ], 44 | "data": { 45 | "google": { 46 | "expect_user_response": true, 47 | "is_ssml": false, 48 | "no_input_prompts": [] 49 | } 50 | } 51 | }, 52 | "score": 1 53 | }, 54 | "status": { 55 | "code": 200, 56 | "errorType": "success" 57 | }, 58 | "sessionId": "e04c76bf-6e16-4ccb-ab10-5da3a4187289" 59 | } -------------------------------------------------------------------------------- /webhook/welcome.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict' 18 | 19 | const ChirpSessionManager = require('./chirp-session-manager') 20 | 21 | const { logError } = require('./logging') 22 | const { makeCard } = require('./sharing-card') 23 | 24 | /** 25 | * Added for testing whether or not we want to allow usage media playback via Assistant on devices. 26 | */ 27 | const IS_ASSISTANT_ENABLED = true 28 | 29 | exports.handleWelcome = (app, sessionId) => { 30 | let hasScreen = app.hasSurfaceCapability(app.SurfaceCapabilities.SCREEN_OUTPUT) 31 | 32 | if(hasScreen && !IS_ASSISTANT_ENABLED) { 33 | // If we're in the assistant or Allo, don't do anything fun, only push users to website 34 | // app.tell closes the conversation so there's no followup 35 | return app.tell( 36 | app.buildRichResponse() 37 | .addSimpleResponse('Check out Mix Lab on the web for the full experience!') 38 | .addBasicCard(makeCard(app)) 39 | ) 40 | } else { 41 | // Proceed as normal, let's create a session and say hi via responses given to us on Dialogflow 42 | ChirpSessionManager.createSession(sessionId) 43 | .then(() => { 44 | return app.ask(app.getIncomingRichResponse()) 45 | }) 46 | .catch(error => { 47 | logError('handleWelcome', error) 48 | return app.tell('Sorry, I couldn\'t create your session. Please try again.') 49 | }) 50 | } 51 | } -------------------------------------------------------------------------------- /website/.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "say-to-play" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "static", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "polyfills": "polyfills.ts", 17 | "test": "test.ts", 18 | "tsconfig": "tsconfig.app.json", 19 | "testTsconfig": "tsconfig.spec.json", 20 | "prefix": "app", 21 | "styles": [ 22 | "styles.scss" 23 | ], 24 | "scripts": [], 25 | "environmentSource": "environments/environment.ts", 26 | "environments": { 27 | "dev": "environments/environment.ts", 28 | "prod": "environments/environment.prod.ts" 29 | } 30 | } 31 | ], 32 | "e2e": { 33 | "protractor": { 34 | "config": "./protractor.conf.js" 35 | } 36 | }, 37 | "lint": [ 38 | { 39 | "project": "src/tsconfig.app.json", 40 | "exclude": "**/node_modules/**" 41 | }, 42 | { 43 | "project": "src/tsconfig.spec.json", 44 | "exclude": "**/node_modules/**" 45 | }, 46 | { 47 | "project": "e2e/tsconfig.e2e.json", 48 | "exclude": "**/node_modules/**" 49 | } 50 | ], 51 | "test": { 52 | "karma": { 53 | "config": "./karma.conf.js" 54 | } 55 | }, 56 | "defaults": { 57 | "styleExt": "scss", 58 | "component": {} 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /website/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "src/assets/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /website/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /static 3 | 4 | # dependencies 5 | /node_modules 6 | bower_components 7 | 8 | # IDEs and editors 9 | /.idea 10 | .project 11 | .classpath 12 | .c9/ 13 | *.launch 14 | .settings/ 15 | *.sublime-workspace 16 | 17 | # IDE - VSCode 18 | .vscode/* 19 | !.vscode/settings.json 20 | !.vscode/tasks.json 21 | !.vscode/launch.json 22 | !.vscode/extensions.json 23 | 24 | # misc 25 | /.sass-cache 26 | /connect.lock 27 | /coverage 28 | /libpeerconnection.log 29 | npm-debug.log 30 | testem.log 31 | /typings 32 | .netrc 33 | 34 | # e2e 35 | /e2e/*.js 36 | /e2e/*.map 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db 41 | 42 | # SSH Keys 43 | server.key 44 | server.cer 45 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Mix Lab Website 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.3.2. 4 | 5 | Requires Angular cli `npm install -g @angular/cli@latest` 6 | 7 | ## Development server 8 | Run `npm install` for deps, also run `bower install` for Polymer deps. 9 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 10 | 11 | ### Running HTTPS locally 12 | In order to use the microphone on your local codebase on a mobile device, you'll need the browser to think it's https. 13 | First create a certificate/key set: `openssl genrsa -out server.key 2048; openssl req -new -x509 -sha256 -key server.key -out server.cer -days 365 -subj /CN=0.0.0.0` 14 | Run `npm run serve-https` 15 | 16 | Note: you'll have to bypass the "Your connection is not private" message. 17 | In chrome, click ADVANCED —> "Proceed to [your IP address] (unsafe)" 18 | 19 | ## Code scaffolding 20 | 21 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 22 | 23 | ## Build 24 | 25 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 26 | 27 | ## Running unit tests 28 | 29 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 30 | 31 | ## Running end-to-end tests 32 | 33 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 34 | Before running the tests make sure you are serving the app via `ng serve`. 35 | 36 | ## Further help 37 | 38 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 39 | 40 | ## Deployment 41 | To push to a version, run: `npm run stage` 42 | -------------------------------------------------------------------------------- /website/app.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | runtime: python27 16 | api_version: 1 17 | threadsafe: true 18 | 19 | handlers: 20 | 21 | - url: /styles.css 22 | static_files: static/styles.css 23 | upload: static/styles.css 24 | secure: always 25 | 26 | # scripts/css 27 | - url: /(.*\.(js|css)) 28 | static_files: static/\1 29 | upload: static/(.*\.(js|css)) 30 | secure: always 31 | 32 | # image files 33 | - url: /(.*\.(bmp|gif|ico|jpeg|jpg|png|svg)) 34 | static_files: static/\1 35 | upload: static/(.*\.(bmp|gif|ico|jpeg|jpg|png|svg)) 36 | secure: always 37 | 38 | # media files 39 | - url: /(.*\.(mp3|m4a)) 40 | static_files: static/\1 41 | upload: static/(.*\.(mp3|m4a)) 42 | secure: always 43 | 44 | - url: /assets/voice-button.html 45 | static_files: static/assets/voice-button.html 46 | upload: static/assets/voice-button.html 47 | secure: always 48 | 49 | - url: /assets/(.*\.(html)) 50 | static_files: static/assets/\1 51 | upload: static/assets/(.*\.(html)) 52 | secure: always 53 | 54 | - url: /jam/.* 55 | static_files: static/jam.html 56 | upload: static/jam.html 57 | secure: always 58 | 59 | - url: /jam 60 | static_files: static/jam.html 61 | upload: static/jam.html 62 | secure: always 63 | 64 | - url: / 65 | static_files: static/index.html 66 | upload: static/index.html 67 | secure: always 68 | 69 | - url: /about 70 | static_files: static/index.html 71 | upload: static/index.html 72 | secure: always 73 | 74 | - url: /link?.* 75 | static_files: static/index.html 76 | upload: static/index.html 77 | secure: always 78 | 79 | skip_files: 80 | - ^.idea/.* 81 | - ^.git/.* 82 | - ^node_modules/.* 83 | - ^e2e/.* 84 | - ^(.*/)?.*\.DS_Store$ 85 | - ^src/.* 86 | - ^style/.* 87 | - ^(.*/)?.*\.swp$ 88 | -------------------------------------------------------------------------------- /website/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "say-to-play", 3 | "description": "", 4 | "main": "", 5 | "authors": [ 6 | "Jason Farrell " 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "dependencies": { 12 | "polymer": "Polymer/polymer#^2.0.0", 13 | "paper-behaviors": "PolymerElements/paper-behaviors#1 - 2", 14 | "paper-styles": "PolymerElements/paper-styles#1 - 2", 15 | "paper-button": "PolymerElements/paper-button#1 - 2", 16 | "webcomponentsjs": "^1.0.8", 17 | "webrtc-adapter": "5.0.6" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /website/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { AppPage } from './app.po'; 18 | 19 | describe('say-to-play App', () => { 20 | let page: AppPage; 21 | 22 | beforeEach(() => { 23 | page = new AppPage(); 24 | }); 25 | 26 | it('should display welcome message', () => { 27 | page.navigateTo(); 28 | expect(page.getParagraphText()).toEqual('Welcome to app!'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /website/e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { browser, by, element } from 'protractor'; 18 | 19 | export class AppPage { 20 | navigateTo() { 21 | return browser.get('/'); 22 | } 23 | 24 | getParagraphText() { 25 | return element(by.css('app-root h1')).getText(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /website/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /website/karma.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Karma configuration file, see link for more information 18 | // https://karma-runner.github.io/1.0/config/configuration-file.html 19 | 20 | module.exports = function (config) { 21 | config.set({ 22 | basePath: '', 23 | frameworks: ['jasmine', '@angular/cli'], 24 | plugins: [ 25 | require('karma-jasmine'), 26 | require('karma-chrome-launcher'), 27 | require('karma-jasmine-html-reporter'), 28 | require('karma-coverage-istanbul-reporter'), 29 | require('@angular/cli/plugins/karma') 30 | ], 31 | client:{ 32 | clearContext: false // leave Jasmine Spec Runner output visible in browser 33 | }, 34 | coverageIstanbulReporter: { 35 | reports: [ 'html', 'lcovonly' ], 36 | fixWebpackSourcePaths: true 37 | }, 38 | angularCli: { 39 | environment: 'dev' 40 | }, 41 | reporters: ['progress', 'kjhtml'], 42 | port: 9876, 43 | colors: true, 44 | logLevel: config.LOG_INFO, 45 | autoWatch: true, 46 | browsers: ['Chrome'], 47 | singleRun: false 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "say-to-play", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve", 8 | "build": "ng build", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e", 12 | "stage": "ng build --prod; ./share.sh; say 'need your attention'; gcloud app deploy --no-promote --project=say-to-play; say 'deploy complete'", 13 | "serve-https": "ng serve --ssl true --ssl-key server.key --ssl-cert server.cer --host=0.0.0.0 --disable-host-check" 14 | }, 15 | "private": true, 16 | "dependencies": { 17 | "@angular/animations": "^4.2.4", 18 | "@angular/common": "^4.2.4", 19 | "@angular/compiler": "^4.2.4", 20 | "@angular/core": "^4.2.4", 21 | "@angular/forms": "^4.2.4", 22 | "@angular/http": "^4.2.4", 23 | "@angular/platform-browser": "^4.2.4", 24 | "@angular/platform-browser-dynamic": "^4.2.4", 25 | "@angular/router": "^4.2.4", 26 | "@codebakery/origami": "^1.3.2", 27 | "@tweenjs/tween.js": "^17.1.0", 28 | "@types/youtube": "0.0.29", 29 | "angulartics2": "^3.2.0", 30 | "core-js": "^2.4.1", 31 | "dat.gui": "^0.6.1", 32 | "gsap": "^1.20.2", 33 | "indefinite-article": "0.0.2", 34 | "ng-inline-svg": "^4.0.1", 35 | "ng2-clipboard": "^1.0.35", 36 | "object-assign": "^4.1.1", 37 | "rxjs": "^5.4.2", 38 | "simplex-noise": "^2.3.0", 39 | "stats.js": "^0.17.0", 40 | "three": "^0.87.1", 41 | "tone": "^0.10.0", 42 | "ts-clipboard": "^1.0.15", 43 | "web-animations-js": "^2.3.1", 44 | "zone.js": "0.8.17" 45 | }, 46 | "devDependencies": { 47 | "@angular/cli": "^1.3.2", 48 | "@angular/compiler-cli": "^4.2.4", 49 | "@angular/language-service": "^4.2.4", 50 | "@types/jasmine": "~2.5.53", 51 | "@types/jasminewd2": "~2.0.2", 52 | "@types/node": "~6.0.60", 53 | "@types/tone": "github:UseAllFive/TypeScript", 54 | "api-ai-javascript": "^2.0.0-beta.21", 55 | "bourbon": "^4.3.4", 56 | "bourbon-neat": "^2.1.0", 57 | "codelyzer": "~3.1.1", 58 | "jasmine-core": "~2.6.2", 59 | "jasmine-spec-reporter": "~4.1.0", 60 | "karma": "~1.7.0", 61 | "karma-chrome-launcher": "~2.1.1", 62 | "karma-cli": "~1.0.1", 63 | "karma-coverage-istanbul-reporter": "^1.2.1", 64 | "karma-jasmine": "~1.1.0", 65 | "karma-jasmine-html-reporter": "^0.2.2", 66 | "protractor": "~5.1.2", 67 | "ts-node": "~3.2.0", 68 | "tslint": "~5.3.2", 69 | "typescript": "~2.3.3" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /website/protractor.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Protractor configuration file, see link for more information 18 | // https://github.com/angular/protractor/blob/master/lib/config.ts 19 | 20 | const { SpecReporter } = require('jasmine-spec-reporter'); 21 | 22 | exports.config = { 23 | allScriptsTimeout: 11000, 24 | specs: [ 25 | './e2e/**/*.e2e-spec.ts' 26 | ], 27 | capabilities: { 28 | 'browserName': 'chrome' 29 | }, 30 | directConnect: true, 31 | baseUrl: 'http://localhost:4200/', 32 | framework: 'jasmine', 33 | jasmineNodeOpts: { 34 | showColors: true, 35 | defaultTimeoutInterval: 30000, 36 | print: function() {} 37 | }, 38 | onPrepare() { 39 | require('ts-node').register({ 40 | project: 'e2e/tsconfig.e2e.json' 41 | }); 42 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /website/share.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Copies our metadata specific for the /jam/* pages to a new html file. 16 | awk 'NR==FNR { a = a$0; next } { sub(/.*/, a); print;}' src/assets/share-jam.html static/index.html > static/jam.html 17 | -------------------------------------------------------------------------------- /website/src/app/app-routing-transitions.ts: -------------------------------------------------------------------------------- 1 | import {trigger, state, animate, style, transition} from '@angular/animations'; 2 | 3 | // Global router transition 4 | export function routerTransition() { 5 | return fade(); 6 | } 7 | 8 | // Fade in/out on route change 9 | export function fade() { 10 | return trigger('routerTransition', [ 11 | state('void', style({ 12 | position: 'fixed', 13 | })), 14 | state('*', style({ 15 | position: 'fixed', 16 | })), 17 | transition(':enter', [ 18 | style({ 19 | opacity: '0' 20 | }), 21 | animate('0.5s ease-in-out', style({ 22 | opacity: '1' 23 | })) 24 | ]), 25 | transition(':leave', [ 26 | style({ 27 | opacity: '1' 28 | }), 29 | animate('0.5s ease-in-out', style({ 30 | opacity: '0' 31 | })) 32 | ]) 33 | ]); 34 | } 35 | -------------------------------------------------------------------------------- /website/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { NgModule } from '@angular/core'; 18 | import { Routes, RouterModule } from '@angular/router'; 19 | import { HomeComponent } from "./states/home/home.component"; 20 | import { AboutComponent } from "./states/about/about.component"; 21 | import { JamComponent } from "./states/jam/jam.component"; 22 | import { JamResolveGuard } from './guards/jam-resolve.guard'; 23 | import { MultitrackEditorComponent } from "./components/multitrack-editor/multitrack-editor.component"; 24 | import { LinkComponent } from "./states/link/link.component"; 25 | 26 | const routes: Routes = [ 27 | { 28 | path: '', 29 | component: HomeComponent, 30 | }, 31 | { 32 | path: 'jam', 33 | component: JamComponent 34 | }, 35 | { 36 | path: 'about', 37 | component: AboutComponent, 38 | }, 39 | { 40 | path: 'jam/:hashID', 41 | component: JamComponent, 42 | resolve: { 43 | loaded: JamResolveGuard 44 | } 45 | }, 46 | { 47 | path: 'link', 48 | component: LinkComponent, 49 | }, 50 | ]; 51 | 52 | @NgModule({ 53 | imports: [RouterModule.forRoot(routes)], 54 | exports: [RouterModule] 55 | }) 56 | export class AppRoutingModule { } 57 | -------------------------------------------------------------------------------- /website/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
4 | 5 | 6 | 7 |
8 | -------------------------------------------------------------------------------- /website/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/app/app.component.scss -------------------------------------------------------------------------------- /website/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { TestBed, async } from '@angular/core/testing'; 18 | import { RouterTestingModule } from '@angular/router/testing'; 19 | 20 | import { AppComponent } from './app.component'; 21 | 22 | describe('AppComponent', () => { 23 | beforeEach(async(() => { 24 | TestBed.configureTestingModule({ 25 | imports: [ 26 | RouterTestingModule 27 | ], 28 | declarations: [ 29 | AppComponent 30 | ], 31 | }).compileComponents(); 32 | })); 33 | 34 | it('should create the app', async(() => { 35 | const fixture = TestBed.createComponent(AppComponent); 36 | const app = fixture.debugElement.componentInstance; 37 | expect(app).toBeTruthy(); 38 | })); 39 | 40 | it(`should have as title 'app'`, async(() => { 41 | const fixture = TestBed.createComponent(AppComponent); 42 | const app = fixture.debugElement.componentInstance; 43 | expect(app.title).toEqual('app'); 44 | })); 45 | 46 | it('should render title in a h1 tag', async(() => { 47 | const fixture = TestBed.createComponent(AppComponent); 48 | fixture.detectChanges(); 49 | const compiled = fixture.debugElement.nativeElement; 50 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); 51 | })); 52 | }); 53 | -------------------------------------------------------------------------------- /website/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, AfterViewInit, Renderer2, HostListener } from '@angular/core'; 18 | import { NavigationEnd, Router } from '@angular/router'; 19 | import { EventsService } from './services/events.service'; 20 | import { FallbackService } from './services/fallback.service'; 21 | import {Angulartics2GoogleAnalytics} from "angulartics2"; 22 | 23 | @Component({ 24 | selector: 'app-root', 25 | templateUrl: './app.component.html', 26 | styleUrls: ['./app.component.scss'] 27 | }) 28 | export class AppComponent implements AfterViewInit { 29 | containerClass: string; 30 | isTouch = false; 31 | fallback = { 32 | supported: true, 33 | message: 'This browser does not support the features included in this app.', 34 | }; 35 | 36 | @HostListener('visibilitychange') onVisibilityChange() { 37 | this.checkFocus(); 38 | } 39 | 40 | @HostListener('window:focus') onFocus() { 41 | this.checkFocus(); 42 | } 43 | 44 | @HostListener('window:blur') onBlur() { 45 | this.checkFocus(); 46 | } 47 | 48 | constructor( 49 | private _router: Router, 50 | private render: Renderer2, 51 | public eventsService: EventsService, 52 | private fallbackService: FallbackService, 53 | public angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics 54 | ) { 55 | this.isTouch = 'ontouchstart' in document.documentElement; 56 | this._router.events.subscribe((event: any) => { 57 | // On route change: 58 | // add page class for component-component styling 59 | if (event instanceof NavigationEnd ) { 60 | const slug = event.url.split('/').slice(1)[0]; 61 | slug ? this.setPageClass(slug) : this.setPageClass('/'); 62 | } 63 | }); 64 | 65 | // Check browser support from service 66 | this.fallbackService.checkBrowserSupport().then(res => { 67 | this.fallback = ((res) ? res : null); 68 | }); 69 | } 70 | 71 | setPageClass(slug) { 72 | if (slug === '/') { 73 | this.containerClass = 'state-home'; 74 | } else { 75 | this.containerClass = `state-${slug.replace(/\//g, '-')}`; 76 | } 77 | } 78 | 79 | checkFocus() { 80 | this.eventsService.broadcast('songPause', document.hasFocus()); 81 | } 82 | 83 | // Show/Hide controls based on location 84 | ngAfterViewInit() { 85 | const body = document.querySelector('.dg'); 86 | this.render.setStyle(body, 'visibility', 'hidden'); 87 | 88 | if (window.location.hostname === 'localhost') { 89 | this.render.removeStyle(body, 'visibility'); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /website/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { BrowserModule } from '@angular/platform-browser'; 18 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 19 | import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 20 | 21 | import { AppRoutingModule } from './app-routing.module'; 22 | import { AppComponent } from './app.component'; 23 | import { InlineSVGModule } from 'ng-inline-svg'; 24 | import { HomeComponent } from './states/home/home.component'; 25 | import { JamComponent } from './states/jam/jam.component'; 26 | import { MultitrackEditorComponent } from './components/multitrack-editor/multitrack-editor.component'; 27 | import { PolymerModule } from '@codebakery/origami'; 28 | import { IntentService} from './services/intent.service'; 29 | import { EventsService } from './services/events.service'; 30 | import {HttpModule} from "@angular/http"; 31 | import {StemService} from "./services/stem.service"; 32 | import { AboutComponent } from './states/about/about.component'; 33 | import { CloseButtonComponent } from './components/close-button/close-button.component'; 34 | import { SocialComponent } from './components/social/social.component'; 35 | import { TooltipComponent } from './components/tooltip/tooltip.component'; 36 | import { JamResolveGuard } from './guards/jam-resolve.guard'; 37 | import { VolumeButtonComponent } from './components/volume-button/volume-button.component'; 38 | import {SuggestionService} from "./services/suggestion.service"; 39 | import { FallbackComponent } from './components/fallback/fallback.component'; 40 | import { ClipboardService } from 'ng2-clipboard/ng2-clipboard'; 41 | import { LoaderComponent } from './components/loader/loader.component'; 42 | import { Angulartics2Module, Angulartics2GoogleAnalytics } from 'angulartics2'; 43 | import { FallbackService } from './services/fallback.service'; 44 | import { LinkComponent } from './states/link/link.component'; 45 | import { SafePipe } from './pipes/safe.pipe'; 46 | 47 | @NgModule({ 48 | declarations: [ 49 | AppComponent, 50 | MultitrackEditorComponent, 51 | HomeComponent, 52 | JamComponent, 53 | AboutComponent, 54 | CloseButtonComponent, 55 | SocialComponent, 56 | TooltipComponent, 57 | VolumeButtonComponent, 58 | FallbackComponent, 59 | LoaderComponent, 60 | LinkComponent, 61 | SafePipe, 62 | ], 63 | imports: [ 64 | BrowserModule, 65 | BrowserAnimationsModule, 66 | AppRoutingModule, 67 | InlineSVGModule, 68 | PolymerModule.forRoot(), 69 | HttpModule, 70 | Angulartics2Module.forRoot([ Angulartics2GoogleAnalytics ]), 71 | ], 72 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 73 | providers: [ 74 | IntentService, 75 | EventsService, 76 | StemService, 77 | JamResolveGuard, 78 | SuggestionService, 79 | ClipboardService, 80 | FallbackService, 81 | ], 82 | bootstrap: [AppComponent] 83 | }) 84 | export class AppModule { } 85 | -------------------------------------------------------------------------------- /website/src/app/classes/stem-player.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {Tone, Synth, Sampler, Sequence, Player, Transport, TransportTime, Analyser, Time, Master, now} from 'tone' 18 | import TweenMax from 'gsap'; 19 | import {Stem} from "./stem" 20 | 21 | declare var window; 22 | 23 | export class StemPlayer { 24 | 25 | public synth; 26 | public stems: Object = {}; 27 | private volumeTimeout; 28 | 29 | constructor() { 30 | this.synth = new Synth().toMaster(); 31 | window.Storage = {ctx: this.synth.context}; 32 | //this.synth.triggerAttackRelease('C4', 0.5); 33 | } 34 | 35 | loadTrack(stem: Stem) { 36 | return new Promise((resolve) => { 37 | let fft = new Analyser('waveform', 1024); 38 | stem.player = new Player( 39 | stem.url, () => { 40 | stem.player.loopStart = stem.loopStart; 41 | stem.player.loopEnd = stem.loopEnd; 42 | stem.player.loop = stem.loop; 43 | if (Transport.state === 'stopped') { 44 | Transport.start(now() + stem.loopStart, 0); 45 | stem.player.start(now(), 0); 46 | } else { 47 | stem.player.volume.value = -100; 48 | stem.player.volume.rampTo(stem.volume, 1); 49 | const offset = Transport.seconds % stem.loopDuration; 50 | stem.player.start(now(), offset + stem.loopStart); 51 | } 52 | this.stems[stem.slug] = stem; 53 | resolve({stem: stem, analyser: fft._analyser}); 54 | }).fan(fft).toMaster(); 55 | }); 56 | } 57 | 58 | playOneOff(url: string) { 59 | return new Promise((resolve) => { 60 | let player = new Player({url: url, autostart: true, onload: () => { 61 | resolve(player.buffer.duration); 62 | }}).toMaster(); 63 | }); 64 | } 65 | 66 | remove(stem: Stem) { 67 | stem.setVolume(stem.MIN_VOLUME, 1.3).then(() => { 68 | stem.player.dispose(); 69 | delete this.stems[stem.slug]; 70 | }); 71 | } 72 | 73 | getTracksByType(type, currentTrackSlug) { 74 | let matches = []; 75 | Object.entries(this.stems).forEach(([key, stem]) => { 76 | if ( 77 | stem.type === type && 78 | stem.slug !== currentTrackSlug 79 | ) { 80 | matches.push(stem); 81 | } 82 | }); 83 | return matches; 84 | } 85 | 86 | setVolume(volume: number) { 87 | TweenMax.to(Master.volume, 0.5, {value: volume}); 88 | } 89 | 90 | pause() { 91 | clearTimeout(this.volumeTimeout); 92 | Object.entries(this.stems).forEach(([key, stem]) => { 93 | stem.player.volume.rampTo(-100, 0.5); 94 | }); 95 | this.volumeTimeout = setTimeout(() => { 96 | Object.entries(this.stems).forEach(([key, stem]) => { 97 | stem.player.stop(); 98 | stem.playing = false; 99 | }); 100 | }, 500); 101 | } 102 | 103 | resume() { 104 | clearTimeout(this.volumeTimeout); 105 | Object.entries(this.stems).forEach(([key, stem]) => { 106 | const offset = Transport.seconds % stem.loopDuration; 107 | stem.player.start(now(), offset + stem.loopStart); 108 | stem.player.volume.value = -100; 109 | stem.player.volume.rampTo(stem.volume, 0.5); 110 | }); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /website/src/app/components/close-button/close-button.component.html: -------------------------------------------------------------------------------- 1 |
5 | 9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /website/src/app/components/close-button/close-button.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | .close { 4 | @include padding($bumper $bumper-mobile null null); 5 | @include position(fixed, 0 0 null null); 6 | cursor: pointer; 7 | outline: none; 8 | transform: translate3d(0, 0, 0); 9 | z-index: 5; 10 | 11 | @include grid-media($m) { 12 | @include padding($bumper $bumper null null); 13 | @include position(fixed, 0 0 null null); 14 | } 15 | } 16 | 17 | .close-button { 18 | @include svg(17px, 17px, $white); 19 | display: block; 20 | 21 | @include grid-media($m) { 22 | @include svg(26px, 26px, $white); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /website/src/app/components/close-button/close-button.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { CloseButtonComponent } from './close-button.component'; 20 | 21 | describe('CloseButtonComponent', () => { 22 | let component: CloseButtonComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ CloseButtonComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(CloseButtonComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should create', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/components/close-button/close-button.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, AfterViewInit, Input, Output, EventEmitter } from '@angular/core'; 18 | import { trigger, state, style, transition, animate } from '@angular/animations'; 19 | 20 | const DELAY = 300; 21 | 22 | @Component({ 23 | selector: 'app-close-button', 24 | templateUrl: './close-button.component.html', 25 | styleUrls: ['./close-button.component.scss'], 26 | animations: [ 27 | trigger('spin', [ 28 | state('out', style({ 29 | opacity: 0, 30 | transform: 'rotate(-280deg)', 31 | })), 32 | state('in', style({ 33 | opacity: 1, 34 | transform: 'rotate(0deg)', 35 | })), 36 | transition('out <=> in', animate('0.6s cubic-bezier(0.165, 0.840, 0.440, 1.000)')) 37 | ]), 38 | ] 39 | }) 40 | export class CloseButtonComponent implements AfterViewInit { 41 | @Output() notify: EventEmitter = new EventEmitter(); 42 | spinState = 'out'; 43 | 44 | constructor() { } 45 | 46 | ngAfterViewInit() { 47 | setTimeout(() => { 48 | this.spinState = 'in'; 49 | }, DELAY); 50 | } 51 | 52 | close() { 53 | this.spinState = 'out'; 54 | this.notify.emit(false); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /website/src/app/components/fallback/fallback.component.html: -------------------------------------------------------------------------------- 1 |
4 |
6 | {{ message ? message : 'This browser doesn’t support speech recognition.' }}
7 |
8 | Try using a different browser, such as Google Chrome on either Desktop or Android. 9 |
10 |
11 | -------------------------------------------------------------------------------- /website/src/app/components/fallback/fallback.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | .fallback { 4 | @include position(fixed, 0 0 0 0); 5 | height: 100%; 6 | width: 100%; 7 | } 8 | 9 | .message { 10 | @extend %body-m; 11 | @include align-all(absolute); 12 | @include padding($spacing-l $spacing-s); 13 | color: $white; 14 | max-width: 800px; 15 | text-align: center; 16 | width: 80%; 17 | z-index: 2; 18 | 19 | a { 20 | color: $white; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /website/src/app/components/fallback/fallback.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { FallbackComponent } from './fallback.component'; 20 | 21 | describe('FallbackComponent', () => { 22 | let component: FallbackComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ FallbackComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(FallbackComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should be created', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/components/fallback/fallback.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, OnInit, Input } from '@angular/core'; 18 | 19 | @Component({ 20 | selector: 'app-fallback', 21 | templateUrl: './fallback.component.html', 22 | styleUrls: ['./fallback.component.scss'] 23 | }) 24 | export class FallbackComponent implements OnInit { 25 | @Input() message: string; 26 | 27 | constructor() { } 28 | 29 | ngOnInit() { 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /website/src/app/components/loader/loader.component.html: -------------------------------------------------------------------------------- 1 |
4 | 5 | 6 | 7 | 8 | 9 |
10 | -------------------------------------------------------------------------------- /website/src/app/components/loader/loader.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | .loader { 4 | @include align-all(absolute); 5 | @include svg(100%, 100%, currentColor); 6 | opacity: 0; 7 | pointer-events: none; 8 | max-width: 100px; 9 | transition: opacity $transition-speed; 10 | width: 100%; 11 | 12 | &.active { 13 | opacity: 1; 14 | } 15 | 16 | /deep/ circle { 17 | &:nth-child(1) { 18 | animation: 0.7s loader 0s infinite; 19 | } 20 | 21 | &:nth-child(2) { 22 | animation: 0.7s loader 0.3s infinite; 23 | } 24 | 25 | &:nth-child(3) { 26 | animation: 0.7s loader 0.5s infinite; 27 | } 28 | } 29 | } 30 | 31 | @keyframes loader { 32 | to { 33 | fill-opacity: 0; 34 | } 35 | from { 36 | fill-opacity: 1; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /website/src/app/components/loader/loader.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoaderComponent } from './loader.component'; 4 | 5 | describe('LoaderComponent', () => { 6 | let component: LoaderComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LoaderComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoaderComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /website/src/app/components/loader/loader.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { EventsService } from '../../services/events.service'; 3 | 4 | @Component({ 5 | selector: 'app-loader', 6 | templateUrl: './loader.component.html', 7 | styleUrls: ['./loader.component.scss'] 8 | }) 9 | export class LoaderComponent implements OnInit { 10 | @Input() toggle: boolean = false; 11 | 12 | constructor( 13 | public eventsService: EventsService, 14 | ) { } 15 | 16 | ngOnInit() { 17 | this.eventsService.on('toggleLoader', (toggle) => { 18 | this.toggle = toggle; 19 | }); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /website/src/app/components/multitrack-editor/multitrack-editor.component.html: -------------------------------------------------------------------------------- 1 |
5 | 8 | 9 |
10 |
11 | {{mobileIntroText}} 12 |
13 |
{{startCopy}}
14 |
17 | 26 | 27 |
28 | 30 | 31 | -------------------------------------------------------------------------------- /website/src/app/components/multitrack-editor/multitrack-editor.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | canvas { 4 | position: fixed; 5 | left: 0; 6 | top: 0; 7 | } 8 | 9 | .nav { 10 | position: absolute; 11 | bottom: 0; 12 | left: 0; 13 | z-index: 4; 14 | width: 30%; 15 | background: rgba(0, 0, 0, 0.3); 16 | padding: 10px; 17 | } 18 | 19 | a { 20 | text-decoration: none; 21 | border-bottom: 1px solid #fff; 22 | cursor: pointer; 23 | font-size: 13px; 24 | } 25 | 26 | .mic { 27 | @include position(relative, null null $bumper-mobile 50%); 28 | height: 100px; 29 | transform-origin: bottom center; 30 | transform: translateX(-50%) scale(0.5); // Scale is a hack to get the button smaller since `diameter` wasnt working 31 | width: 100px; 32 | z-index: 3; 33 | 34 | @include grid-media($m) { 35 | @include position(relative, null null $bumper 50%); 36 | transform: translateX(-50%) scale(1); 37 | } 38 | } 39 | 40 | .voice-wrap { 41 | @include position(fixed, null 0 0 0); 42 | @include margin(0 auto); 43 | @include size(50px auto); 44 | transform: translateY(30px); 45 | transition: all 0.25s ease-out; 46 | display: block; 47 | z-index: 10; 48 | opacity: 0; 49 | pointer-events: none; 50 | 51 | @include grid-media($m) { 52 | @include size(100px auto); 53 | } 54 | 55 | &.visible { 56 | transform: translateY(0); 57 | opacity: 1; 58 | pointer-events: auto; 59 | } 60 | } 61 | 62 | .mobile-play { 63 | @include position(fixed, 0 0 0 0); 64 | background-color: rgba($black, 0.6); 65 | display: block; 66 | height: 100%; 67 | opacity: 0; 68 | pointer-events: none; 69 | transition: all 0.5s 0s; 70 | width: 100%; 71 | z-index: 999; 72 | 73 | &.active { 74 | opacity: 1; 75 | pointer-events: auto; 76 | transition: all 0.5s; 77 | } 78 | 79 | @include grid-media($m) { 80 | display: none; 81 | } 82 | } 83 | 84 | .play-icon { 85 | @include position(absolute, 50% null null 50%); 86 | @include svg(78px, 78px, $white); 87 | display: block; 88 | transform: translate(-50%, -50%); 89 | } 90 | 91 | .mobileCTA { 92 | @extend %button-outline; 93 | position: fixed; 94 | bottom: 45px; 95 | left: 50%; 96 | transform: translateX(-50%); 97 | z-index: 1000; 98 | } 99 | 100 | .mobileIntro { 101 | position: fixed; 102 | left: 50%; 103 | top: 50%; 104 | transform: translate(-50%, -50%); 105 | z-index: 1000; 106 | text-align: center; 107 | width: 80%; 108 | color: $white; 109 | 110 | &.top { 111 | transform: translateX(-50%); 112 | top: 12%; 113 | } 114 | } 115 | 116 | 117 | -------------------------------------------------------------------------------- /website/src/app/components/multitrack-editor/multitrack-editor.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { MultitrackEditorComponent } from './multitrack-editor.component'; 20 | 21 | describe('MultitrackEditorComponent', () => { 22 | let component: MultitrackEditorComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ MultitrackEditorComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(MultitrackEditorComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should be created', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/components/social/social.component.html: -------------------------------------------------------------------------------- 1 | 53 | 58 | 59 | -------------------------------------------------------------------------------- /website/src/app/components/social/social.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | .social { 4 | @extend %body-m; 5 | @include position(fixed, null $bumper-mobile $bumper-mobile null); 6 | color: rgba($white, 0.5); 7 | transition: all $transition-speed; 8 | z-index: 999999; 9 | 10 | &.active { 11 | color: $white; 12 | } 13 | 14 | @include grid-media($m) { 15 | @include position(fixed, null $bumper $bumper null); 16 | } 17 | } 18 | 19 | .text { 20 | @include position(absolute, 50% 0 null null); 21 | cursor: pointer; 22 | display: block; 23 | font-size: 16px; 24 | opacity: 1; 25 | pointer-events: auto; 26 | transform: translateY(-50%); 27 | transition: all $transition-speed; 28 | white-space: nowrap; 29 | z-index: 13; 30 | 31 | @include grid-media($m) { 32 | font-size: 20px; 33 | } 34 | 35 | @media (max-height: 850px) and (max-width: 768px) { 36 | font-size: 14px; 37 | } 38 | 39 | &.inactive { 40 | opacity: 0; 41 | pointer-events: none; 42 | z-index: 10; 43 | } 44 | } 45 | 46 | .icon-wrap { 47 | display: block; 48 | opacity: 0; 49 | position: relative; 50 | transition: opacity 0.4s; 51 | z-index: 12; 52 | 53 | &.active { 54 | opacity: 1; 55 | } 56 | } 57 | 58 | .icon { 59 | @include svg(22px, 16px, $white); 60 | background: none; 61 | border: none; 62 | cursor: pointer; 63 | display: inline-block; 64 | vertical-align: middle; 65 | 66 | & + & { 67 | margin-left: 5px; 68 | @media (min-width: 375px) { 69 | margin-left: 13px; 70 | } 71 | } 72 | 73 | &.facebook { 74 | @include svg(9px, 20px, $white); 75 | } 76 | 77 | &.google { 78 | @include svg(31px, 16px, $white); 79 | } 80 | 81 | &.link { 82 | @include svg(25px, 25px, $white); 83 | } 84 | 85 | @include grid-media($m) { 86 | @include svg(27px, 21px, $white); 87 | 88 | & + & { 89 | margin-left: 10px; 90 | } 91 | 92 | &.facebook { 93 | @include svg(12px, 24px, $white); 94 | } 95 | 96 | &.google { 97 | @include svg(36px, 21px, $white); 98 | } 99 | 100 | &.link { 101 | @include svg(32px, 32px, $white); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /website/src/app/components/social/social.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { SocialComponent } from './social.component'; 20 | 21 | describe('SocialComponent', () => { 22 | let component: SocialComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ SocialComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(SocialComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should create', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/components/tooltip/tooltip.component.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /website/src/app/components/tooltip/tooltip.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | :host { 4 | @include position(fixed, null 0 100px 0); 5 | margin: 0 auto; 6 | overflow: hidden; 7 | width: 90%; 8 | z-index: 9999; 9 | 10 | @include grid-media($m) { 11 | @include position(fixed, null $spacing-m 75px auto); 12 | max-width: 360px; 13 | 14 | &.copied { 15 | &::after { 16 | content: 'Link copied to clipboard!'; 17 | } 18 | } 19 | } 20 | 21 | textarea { 22 | @extend %body; 23 | @include padding(15px 15px 25px); 24 | background-color: $white; 25 | border: none; 26 | border-radius: 15px; 27 | color: $black; 28 | font-size: 16px; 29 | line-height: 1.2; 30 | outline: none; 31 | text-align: center; 32 | resize: none; 33 | width: 100%; 34 | } 35 | 36 | &::after { 37 | @include position(fixed, null null 15px 50%); 38 | content: 'Copy link to clipboard'; 39 | color: $gray; 40 | display: block; 41 | font-size: 11px; 42 | pointer-events: none; 43 | text-align: center; 44 | text-transform: uppercase; 45 | transform: translateX(-50%); 46 | width: 100%; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /website/src/app/components/tooltip/tooltip.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { TooltipComponent } from './tooltip.component'; 20 | 21 | describe('TooltipComponent', () => { 22 | let component: TooltipComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ TooltipComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(TooltipComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should be created', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/components/tooltip/tooltip.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, AfterViewInit, Input, HostListener, ElementRef, ViewChild } from '@angular/core'; 18 | import { EventsService } from '../../services/events.service'; 19 | 20 | const DELAY = 1300; 21 | 22 | @Component({ 23 | selector: 'app-tooltip', 24 | templateUrl: './tooltip.component.html', 25 | styleUrls: ['./tooltip.component.scss'] 26 | }) 27 | export class TooltipComponent implements AfterViewInit { 28 | @ViewChild('textarea') textarea: ElementRef 29 | @Input() autoshow: boolean = false; 30 | @Input() tooltip: string; 31 | loader = false; 32 | 33 | // Close tooltip if clicking anywhere else besides tooltip 34 | @HostListener('document:click', ['$event']) 35 | onClick(event) { 36 | // Wont work if clicking on any SVG/link tag 37 | if (this.el.nativeElement !== event.target && 38 | event.target.localName !== 'span' && 39 | event.target.localName !== 'svg' && 40 | event.target.localName !== 'path' && 41 | event.target.localName !== 'a' && 42 | event.target.localName !== 'app-social' && 43 | event.target.localName !== 'textarea' && 44 | event.target.localName !== 'app-tooltip' 45 | ) { 46 | this.eventsService.broadcast('tooltipState', 'out'); 47 | } 48 | } 49 | 50 | @HostListener('document:touchstart', ['$event']) 51 | onTouch(event) { 52 | // Wont work if clicking on any SVG/link tag 53 | if (this.el.nativeElement !== event.target && 54 | event.target.localName !== 'span' && 55 | event.target.localName !== 'svg' && 56 | event.target.localName !== 'path' && 57 | event.target.localName !== 'a' && 58 | event.target.localName !== 'app-social' && 59 | event.target.localName !== 'textarea' && 60 | event.target.localName !== 'app-tooltip' 61 | ) { 62 | this.eventsService.broadcast('tooltipState', 'out'); 63 | } 64 | } 65 | 66 | constructor( 67 | public eventsService: EventsService, 68 | private el: ElementRef, 69 | ) {} 70 | 71 | ngAfterViewInit() { 72 | if (!this.autoshow) { 73 | this.checkLocalStorage(); 74 | } else { 75 | this.showTooltip(); 76 | } 77 | } 78 | 79 | textClick() { 80 | this.textarea.nativeElement.select(); 81 | } 82 | 83 | // Show tooltip 84 | showTooltip() { 85 | setTimeout(() => { 86 | this.eventsService.broadcast('tooltipState', 'in'); 87 | }, DELAY); 88 | } 89 | 90 | checkLocalStorage(): Promise { 91 | return new Promise((resolve, reject) => { 92 | let tooltipStorage = localStorage.getItem('tooltip'); 93 | if (typeof(Storage) !== "undefined") { 94 | if (!tooltipStorage) { 95 | this.eventsService.broadcast('tooltipState', 'out'); 96 | localStorage.setItem('tooltip', 'true'); 97 | resolve(false); 98 | } else { 99 | if (tooltipStorage === 'true') { 100 | resolve(true); 101 | } 102 | } 103 | } else { 104 | resolve(false); 105 | } 106 | }); 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /website/src/app/components/visual-tracks/text-texture.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import objectAssign from 'object-assign'; 18 | 19 | const DEFAULTS = { 20 | background: 'black', 21 | color: 'red', 22 | fontFamily: '\'Poppins\', Helvetica, Arial, sans-serif', // Font family string 23 | fontSize: 50, // px 24 | fontWeight: 500, 25 | letterSpacing: 0, // px 26 | x: 2, 27 | y: 3, 28 | }; 29 | 30 | export class TextTexture { 31 | public dpi = 1; 32 | public width; 33 | public height; 34 | public canvas; 35 | public ctx; 36 | public text = ''; 37 | 38 | constructor(opts = {width: 512, height: 512, dpi: 1}) { 39 | if (opts.dpi !== undefined) { 40 | this.dpi = opts.dpi; 41 | } 42 | if (opts.width !== undefined) { 43 | this.width = opts.width; 44 | } 45 | if (opts.height !== undefined) { 46 | this.height = opts.height; 47 | } 48 | this.makeCanvas(); 49 | } 50 | 51 | makeCanvas() { 52 | this.canvas = document.createElement('canvas'); 53 | this.ctx = this.canvas.getContext('2d'); 54 | this.canvas.width = this.width * this.dpi; 55 | this.canvas.height = this.height * this.dpi; 56 | this.fillColor(); 57 | // Debug 58 | // window.document.body.appendChild(this.canvas); 59 | // this.canvas.style.position = 'fixed'; 60 | // this.canvas.style.top = '0px'; 61 | // this.canvas.style.left = '0px'; 62 | // this.canvas.style.opacity = 0.5; 63 | } 64 | 65 | setDPI(dpi) { 66 | this.dpi = dpi; 67 | this.canvas.width = this.width * this.dpi; 68 | this.canvas.height = this.height * this.dpi; 69 | } 70 | 71 | fillColor(background = DEFAULTS.background) { 72 | // Fill in with black 73 | this.ctx.fillStyle = background; 74 | this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); 75 | } 76 | 77 | setText(text = '', options = {}) { 78 | this.text = text; 79 | // Options 80 | const opts = objectAssign({}, DEFAULTS, options); 81 | 82 | // Clear Drawing Space 83 | this.fillColor(opts.background); 84 | 85 | // Style Settings 86 | this.ctx.font = `${opts.fontWeight} ${opts.fontSize * this.dpi}px ${opts.fontFamily}`; 87 | this.ctx.fillStyle = opts.color; 88 | this.ctx.textBaseline = 'top'; 89 | 90 | // Starting Position 91 | let x = opts.x * this.dpi; 92 | let y = opts.y * this.dpi; 93 | for (let i = 0; i < text.length; i++) { 94 | const c = text.charAt(i); 95 | this.ctx.fillText(c, x, y); 96 | x += this.ctx.measureText(c).width + opts.letterSpacing; 97 | } 98 | 99 | // Explicitly clear the top and right edges 100 | this.ctx.fillStyle = opts.background; 101 | this.ctx.fillRect(0, 0, this.canvas.width, 1); 102 | this.ctx.fillRect(this.canvas.width - 1, 0, 1, this.canvas.height); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /website/src/app/components/visual-tracks/visual-track-vert.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export const vertexShader = ` 18 | void main() { 19 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); 20 | } 21 | `; 22 | -------------------------------------------------------------------------------- /website/src/app/components/volume-button/volume-button.component.html: -------------------------------------------------------------------------------- 1 |
4 | 11 | 12 | 19 | 20 |
21 | -------------------------------------------------------------------------------- /website/src/app/components/volume-button/volume-button.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | .volume-button { 4 | @include position(fixed, $bumper-mobile $bumper-mobile null null); 5 | cursor: pointer; 6 | display: block; 7 | z-index: 5; 8 | 9 | @include grid-media($m) { 10 | @include position(fixed, $bumper $bumper null null); 11 | } 12 | } 13 | 14 | .icon { 15 | @include svg(30px, 30px, $white); 16 | display: block; 17 | transition: all $transition-speed; 18 | 19 | &.mute { 20 | /deep/ svg { 21 | fill: $gray; 22 | } 23 | } 24 | 25 | @include grid-media($m) { 26 | @include svg(40px, 40px, $white); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /website/src/app/components/volume-button/volume-button.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { VolumeButtonComponent } from './volume-button.component'; 20 | 21 | describe('VolumeButtonComponent', () => { 22 | let component: VolumeButtonComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ VolumeButtonComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(VolumeButtonComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should be created', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/components/volume-button/volume-button.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, OnInit, Input } from '@angular/core'; 18 | import { EventsService } from '../../services/events.service'; 19 | 20 | @Component({ 21 | selector: 'app-volume-button', 22 | templateUrl: './volume-button.component.html', 23 | styleUrls: ['./volume-button.component.scss'] 24 | }) 25 | export class VolumeButtonComponent implements OnInit { 26 | @Input() mute: boolean; 27 | 28 | constructor( 29 | private eventsService: EventsService 30 | ) { } 31 | 32 | ngOnInit() { 33 | this.eventsService.on('volumeChange', (mute) => { 34 | this.mute = mute; 35 | }); 36 | } 37 | 38 | toggleVolume() { 39 | this.mute = this.mute === true ? false : true; 40 | this.eventsService.broadcast('volumeChange', this.mute); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /website/src/app/guards/jam-resolve.guard.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Injectable } from '@angular/core'; 18 | import { ActivatedRouteSnapshot, RouterStateSnapshot, Resolve, Router } from '@angular/router'; 19 | import { StemService } from '../services/stem.service'; 20 | 21 | @Injectable() 22 | export class JamResolveGuard implements Resolve { 23 | constructor( 24 | private router: Router, 25 | private stemService: StemService 26 | ) {}; 27 | 28 | resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise { 29 | return this.stemService.load(route.params.hashID).then(res => { 30 | // If response is empty 31 | if (typeof res === 'undefined') { 32 | this.router.navigate(['/not-found']); 33 | return null; 34 | } else { 35 | return res; 36 | } 37 | }); 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /website/src/app/interfaces/intent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export interface Intent { 18 | id?: string; 19 | speech?: string; 20 | action?: string; 21 | parameters?: { 22 | genre?: string; 23 | instrument?: string; 24 | sfx?: string; 25 | genres?; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /website/src/app/interfaces/stem.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {Track} from './track'; 18 | 19 | export interface Stem { 20 | slug: string; 21 | type: string; 22 | name: string; 23 | genre?: string; 24 | url: string; 25 | bars: number; 26 | tempo?: number; 27 | currentPosition?: number; 28 | playing?: boolean; 29 | track?: Track; 30 | } 31 | -------------------------------------------------------------------------------- /website/src/app/interfaces/track.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export interface Track { 18 | slug: string; 19 | name: string; 20 | color: string; 21 | slot: number; 22 | } 23 | -------------------------------------------------------------------------------- /website/src/app/mock/tracks.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {Track} from "../interfaces/track"; 18 | 19 | export const MockTracks: Track[] = [ 20 | { 21 | slug: 'keyboard', 22 | name: 'Keyboard', 23 | color: '#00ff00', 24 | slot: 4 25 | }, 26 | { 27 | slug: 'bass', 28 | name: 'Bass', 29 | color: '#FFD356', 30 | slot: 3 31 | }, 32 | { 33 | slug: 'drums', 34 | name: 'Drums', 35 | color: '#F900FA', 36 | slot: 2 37 | }, 38 | { 39 | slug: 'guitar', 40 | name: 'Guitar', 41 | color: '#00A6FF', 42 | slot: 1 43 | }, 44 | { 45 | slug: 'bonus', 46 | name: 'Bonus', 47 | color: '#00A6FF', 48 | slot: 5 49 | } 50 | ]; 51 | -------------------------------------------------------------------------------- /website/src/app/pipes/safe.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { DomSanitizer} from '@angular/platform-browser'; 3 | 4 | @Pipe({ 5 | name: 'safe' 6 | }) 7 | export class SafePipe implements PipeTransform { 8 | constructor(private sanitizer: DomSanitizer) {} 9 | 10 | transform(url, args) { 11 | let safeURL; 12 | if (args === 'youtube') { 13 | safeURL = 'https://www.youtube.com/embed/' + url + '?rel=0&showinfo=0'; 14 | } else { 15 | safeURL = url; 16 | } 17 | return this.sanitizer.bypassSecurityTrustResourceUrl(safeURL); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /website/src/app/services/events.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {Injectable} from "@angular/core"; 18 | import * as Rx from 'rxjs/Rx'; 19 | 20 | @Injectable() 21 | export class EventsService { 22 | public listeners; 23 | public eventsSubject; 24 | public events; 25 | 26 | constructor() { 27 | this.listeners = {}; 28 | this.eventsSubject = new Rx.Subject(); 29 | this.events = Rx.Observable.from(this.eventsSubject); 30 | 31 | this.events.subscribe( 32 | ({name, args}) => { 33 | if (this.listeners[name]) { 34 | for (let listener of this.listeners[name]) { 35 | listener(...args); 36 | } 37 | } 38 | }); 39 | } 40 | 41 | on(name, listener) { 42 | if (!this.listeners[name]) { 43 | this.listeners[name] = []; 44 | } 45 | 46 | this.listeners[name].push(listener); 47 | } 48 | 49 | off(name, listener) { 50 | delete this.listeners[name]; 51 | } 52 | 53 | broadcast(name, ...args) { 54 | this.eventsSubject.next({ 55 | name, 56 | args 57 | }); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /website/src/app/services/intent.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {Injectable} from "@angular/core"; 18 | import {ApiAiClient} from 'api-ai-javascript' 19 | import {Intent} from "../interfaces/intent"; 20 | import {Http} from "@angular/http"; 21 | import {Headers} from '@angular/http'; 22 | 23 | @Injectable() 24 | export class IntentService { 25 | 26 | public client = new ApiAiClient({accessToken: '37c8208d697d4eb7afa5aa00939da9a1'}); 27 | 28 | constructor(public http: Http) {} 29 | 30 | public getIntent(command: String) { 31 | return new Promise((resolve, reject) => { 32 | let headers = new Headers(); 33 | headers.append('Content-Type', 'application/json; charset=utf-8'); 34 | headers.append('Authorization', 'Bearer 37c8208d697d4eb7afa5aa00939da9a1'); 35 | this.http.post( 36 | 'https://api.dialogflow.com/v1/query?v=20170912', 37 | { 38 | query: command, 39 | lang: 'en', 40 | sessionId: this.client.getSessionId(), 41 | originalRequest: { 42 | 'source': 'frontend' 43 | } 44 | },{ 45 | headers: headers 46 | } 47 | ).map(res => res.json()).subscribe((response) => { 48 | if (response.result) { 49 | let intent: Intent = {}; 50 | let result = response.result; 51 | 52 | if ( 53 | result.parameters.genre === '' && 54 | result.parameters.instrument === '' && 55 | result.parameters.sfx === '' && 56 | result.parameters.solo === '' 57 | ) { 58 | reject(); 59 | } else { 60 | // I'm breaking these out individual, because we might not always 61 | // parameters, etc. for each intent. 62 | intent.id = result.metadata.intentId; 63 | intent.action = result.action; 64 | intent.speech = result.resolvedQuery; 65 | intent.parameters = {}; 66 | if (result.parameters) { 67 | intent.parameters.genre = result.parameters.genre; 68 | intent.parameters.instrument = result.parameters.instrument; 69 | intent.parameters.sfx = result.parameters.sfx; 70 | intent.parameters.genres = result.parameters.genres; 71 | } 72 | resolve(intent); 73 | } 74 | } 75 | }); 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /website/src/app/states/about/about.component.html: -------------------------------------------------------------------------------- 1 |
4 |
5 |
About MixLab
6 |
7 |
9 | 14 |
15 |
16 |
17 | MixLab is an experiment that makes it easier for anyone to create music, using simple voice commands. Just say things like "Play me a funky bass," or "Add some jazz drums." Or let MixLab surprise you by simply saying “Play me something." Try it on a Google Home by saying "Hey Google, talk to MixLab," or try it on this site. 18 |
19 |
20 |
21 |
Credits
22 |
23 | Built by
24 | Anthony Tripaldi, LAD, Maya Man, Prit Patel, Yotam Mann, Use All Five, and friends at Google Creative Lab using 25 | Dialogflow 32 | and 33 | Actions on Google. 40 | Learn more on our 41 | Github page, 48 | and check out other 49 | Voice Experiments here.

56 | 57 | Music by
58 | Blake Straus: Composer & Musical Director
59 | Alek Fin: Producer/Engineer

60 | 61 | Musicians
62 | Blake Straus - Fretted instruments, basses, keyboards
63 | Dylan Meek - Keyboards
64 | Roland Gajate Garcia - Drumkit and percussion
65 | DD Horns - Brass and woodwinds
66 | Morgan Paros - Violins
67 | Andrew Synowiec - Fretted instruments
68 | Corbin Jones - Basses and sousaphone
69 | Alison Balbag - Harp
70 | Ian Mallitz - Didgeridoo

71 | Additional Production Assistance:
72 | Daniel Braunstein, Christopher Dwyer, Zac Sager, Mashadi Maximus
73 | Recorded, Mixed, and Mastered at Pro Audio LA
74 |
75 |
76 |
77 | 79 | 80 |
81 | -------------------------------------------------------------------------------- /website/src/app/states/about/about.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | .about { 4 | @include padding(null $bumper-mobile $bumper-mobile); 5 | @include position(fixed, 0 null null 0); 6 | background-color: rgba($black, 0.7); 7 | height: 100%; 8 | overflow-y: scroll; 9 | -webkit-overflow-scrolling: touch; 10 | width: 100%; 11 | z-index: 99999; 12 | user-select: text; 13 | 14 | @include grid-media($m) { 15 | @include padding(null $bumper $bumper); 16 | } 17 | } 18 | 19 | .about-inner { 20 | @include margin($bumper auto null); 21 | @include padding(null $bumper-mobile); 22 | max-width: 688px; 23 | 24 | @include grid-media($m) { 25 | @include margin($spacing-xl auto null); 26 | @include padding(null $bumper); 27 | } 28 | } 29 | 30 | .section { 31 | & + & { 32 | margin-top: $spacing-s; 33 | } 34 | } 35 | 36 | .header { 37 | @extend %cta; 38 | color: $white; 39 | margin-bottom: $bumper; 40 | text-align: center; 41 | } 42 | 43 | .description { 44 | @extend %body; 45 | color: $white; 46 | 47 | a { 48 | color: $white; 49 | text-decoration: underline; 50 | } 51 | } 52 | 53 | .video-wrap { 54 | @include responsive-wrap; 55 | background-color: $black; 56 | margin-bottom: $bumper; 57 | cursor: pointer; 58 | 59 | /deep/ iframe { 60 | @include position(absolute, 0 null null 0); 61 | height: 100%; 62 | width: 100%; 63 | } 64 | } 65 | 66 | .play-button { 67 | @include align-all(absolute); 68 | @include svg(80px, 80px, $white); 69 | align-items: center; 70 | background-color: $lightGray; 71 | border-radius: 50%; 72 | display: flex; 73 | height: $spacing-l; 74 | justify-content: center; 75 | padding: 7px; 76 | width: $spacing-l; 77 | z-index: 99; 78 | 79 | @include grid-media($s) { 80 | height: $spacing-xl; 81 | padding: 15px; 82 | width: $spacing-xl; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /website/src/app/states/about/about.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { ModalComponent } from './modal.component'; 20 | 21 | describe('ModalComponent', () => { 22 | let component: ModalComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ ModalComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(ModalComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should create', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/states/about/about.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, OnInit, Input, Output, EventEmitter, ElementRef, ViewChild } from '@angular/core'; 18 | import { trigger, state, style, transition, animate } from '@angular/animations'; 19 | import { routerTransition } from '../../app-routing-transitions'; 20 | import { EventsService } from '../../services/events.service'; 21 | 22 | const DELAY = 0; 23 | 24 | @Component({ 25 | selector: 'app-about', 26 | templateUrl: './about.component.html', 27 | styleUrls: ['./about.component.scss'], 28 | host: {'[@routerTransition]': ''}, 29 | animations: [routerTransition()], 30 | }) 31 | export class AboutComponent implements OnInit { 32 | @ViewChild('video') video: ElementRef; 33 | @Input() status: boolean; 34 | @Output() modalNotify: EventEmitter = new EventEmitter(); 35 | fadeState = 'out'; 36 | videoID = 'rSc3VoXWMHc'; 37 | 38 | constructor( 39 | private el: ElementRef, 40 | private eventsService: EventsService 41 | ) { } 42 | 43 | ngOnInit() { 44 | setTimeout(() => { 45 | this.fadeState = 'in'; 46 | }, DELAY); 47 | 48 | this.eventsService.broadcast('setTrackState', { 49 | state: 'intro', 50 | secondary: 'greyout' 51 | }); 52 | } 53 | 54 | toggle($event) { 55 | this.fadeState = 'out'; 56 | 57 | setTimeout(() => { 58 | this.status = $event; 59 | this.modalNotify.emit($event); 60 | }, DELAY); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /website/src/app/states/home/home.component.html: -------------------------------------------------------------------------------- 1 |
5 |
9 |
10 | Hey Google, talk to 11 |
12 |
15 |
16 |
Try saying:
17 |
19 |
{{ command || ' '}}
20 |
21 |
22 |
23 | 27 |
28 | 32 | About 33 | 34 | 42 | Privacy & Terms 43 | 44 | 53 | 54 | 63 | 66 | 67 | Preview it Here 68 | 69 |
73 |
74 |
75 | 76 | 80 | 81 | -------------------------------------------------------------------------------- /website/src/app/states/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { HomeComponent } from './home.component'; 20 | 21 | describe('HomeComponent', () => { 22 | let component: HomeComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ HomeComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(HomeComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should be created', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/states/jam/jam.component.html: -------------------------------------------------------------------------------- 1 |
4 | 11 | 12 | 13 |
16 | 17 |
20 | 21 | Tap 22 | Click 23 | the mic and try saying: 24 | 25 | 26 | 27 | Listening... 28 | 29 |
30 |
{{command}}
31 |
32 | 33 |
34 |
35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | -------------------------------------------------------------------------------- /website/src/app/states/jam/jam.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { JamComponent } from './jam.component'; 20 | 21 | describe('JamComponent', () => { 22 | let component: JamComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ JamComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(JamComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should be created', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/states/link/link.component.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /website/src/app/states/link/link.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../assets/scss/shared"; 2 | 3 | :host { 4 | @include position(fixed, 0 null null 0); 5 | background: url('/assets/images/fallback.jpg') center center no-repeat; 6 | background-size: cover; 7 | overflow: hidden; 8 | height: 100%; 9 | width: 100%; 10 | } 11 | 12 | .link { 13 | @include align-all(fixed); 14 | @include padding(null $bumper-mobile); 15 | overflow: hidden; 16 | text-align: center; 17 | color: $white; 18 | width: 100%; 19 | } 20 | 21 | #value { 22 | display: block; 23 | font-size: 16px; 24 | user-select: auto; 25 | } 26 | 27 | button { 28 | @extend %button-outline; 29 | background-color: rgba($white, 0.8); 30 | display: inline-block; 31 | outline: none; 32 | margin-top: $bumper-mobile; 33 | } 34 | -------------------------------------------------------------------------------- /website/src/app/states/link/link.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 18 | 19 | import { ModalComponent } from './modal.component'; 20 | 21 | describe('ModalComponent', () => { 22 | let component: ModalComponent; 23 | let fixture: ComponentFixture; 24 | 25 | beforeEach(async(() => { 26 | TestBed.configureTestingModule({ 27 | declarations: [ ModalComponent ] 28 | }) 29 | .compileComponents(); 30 | })); 31 | 32 | beforeEach(() => { 33 | fixture = TestBed.createComponent(ModalComponent); 34 | component = fixture.componentInstance; 35 | fixture.detectChanges(); 36 | }); 37 | 38 | it('should create', () => { 39 | expect(component).toBeTruthy(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/app/states/link/link.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Component, AfterViewInit } from '@angular/core'; 18 | import { ActivatedRoute } from '@angular/router'; 19 | import { EventsService } from "../../services/events.service"; 20 | 21 | @Component({ 22 | selector: 'app-link', 23 | templateUrl: './link.component.html', 24 | styleUrls: ['./link.component.scss'], 25 | }) 26 | export class LinkComponent implements AfterViewInit { 27 | public url: string; 28 | public text = 'Copy to clipboard'; 29 | 30 | constructor( 31 | private route: ActivatedRoute, 32 | public eventsService: EventsService, 33 | ) { } 34 | 35 | ngAfterViewInit() { 36 | this.eventsService.broadcast('hideCanvas', true); 37 | this.route.queryParams.subscribe(param => { 38 | if (param && param.song) { 39 | this.url = `${this.getURL() + param.song}`; 40 | } 41 | }); 42 | } 43 | 44 | getURL() { 45 | let url; 46 | const port = window.location.port; 47 | const hostname = window.location.hostname; 48 | const protocol = window.location.protocol; 49 | if (protocol && protocol === 'https:') { 50 | url = `${protocol}//${hostname}/jam/`; 51 | } else if (port && port !== '') { 52 | url = `${protocol}//${hostname}:${port}/jam/`; 53 | } else { 54 | url = window.location.origin + '/'; 55 | } 56 | return url; 57 | } 58 | 59 | copy(url) { 60 | let textArea, 61 | copy, 62 | range, 63 | selection; 64 | 65 | textArea = document.createElement('textArea'); 66 | textArea.style.height = "0px"; 67 | textArea.style.left = "-100px"; 68 | textArea.style.opacity = "0"; 69 | textArea.style.fontSize = "16px"; 70 | textArea.style.position = "fixed"; 71 | textArea.style.top = "-100px"; 72 | textArea.style.width = "0px"; 73 | textArea.value = url; 74 | document.body.appendChild(textArea); 75 | 76 | if (navigator.userAgent.match(/ipad|iphone/i)) { 77 | range = document.createRange(); 78 | range.selectNodeContents(textArea); 79 | selection = window.getSelection(); 80 | selection.removeAllRanges(); 81 | selection.addRange(range); 82 | textArea.setSelectionRange(0, 999999); 83 | } else { 84 | textArea.select(); 85 | } 86 | 87 | document.execCommand('copy'); 88 | document.body.removeChild(textArea); 89 | 90 | this.text = 'Link copied to clipboard'; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /website/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/.gitkeep -------------------------------------------------------------------------------- /website/src/assets/images/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/bubble.svg: -------------------------------------------------------------------------------- 1 | Asset 1MixLab -------------------------------------------------------------------------------- /website/src/assets/images/caret.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /website/src/assets/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/fallback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/fallback.jpg -------------------------------------------------------------------------------- /website/src/assets/images/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /website/src/assets/images/favicons/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/android-chrome-256x256.png -------------------------------------------------------------------------------- /website/src/assets/images/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /website/src/assets/images/favicons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #f7692b 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /website/src/assets/images/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /website/src/assets/images/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /website/src/assets/images/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/favicon.ico -------------------------------------------------------------------------------- /website/src/assets/images/favicons/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MixLab", 3 | "icons": [ 4 | { 5 | "src": "assets/images/favicons/android-chrome-192x192.png", 6 | "sizes": "192x192", 7 | "type": "image/png" 8 | } 9 | ], 10 | "theme_color": "#000000", 11 | "background_color": "#000000", 12 | "display": "standalone" 13 | } 14 | -------------------------------------------------------------------------------- /website/src/assets/images/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /website/src/assets/images/google-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/google-home.png -------------------------------------------------------------------------------- /website/src/assets/images/icon-facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/icon-google.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/icon-link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/icon-mic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/icon-twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/mic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /website/src/assets/images/mixlab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | MixLab 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/assets/images/mute.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/images/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /website/src/assets/images/share.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/images/share.jpg -------------------------------------------------------------------------------- /website/src/assets/images/tagline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Start mixing tracks by using your voice. 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/assets/images/volume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/src/assets/scss/_colors.scss: -------------------------------------------------------------------------------- 1 | $gray: #8f8f90; 2 | $lightGray: #E0E0E0; 3 | $white: #ffffff; 4 | $black: #000000; 5 | $blue: #4285F4; 6 | -------------------------------------------------------------------------------- /website/src/assets/scss/_grid.scss: -------------------------------------------------------------------------------- 1 | $bumper: 30px; 2 | $bumper-mobile: 20px; 3 | 4 | // Override default gutter 5 | $neat-grid: ( 6 | gutter: $bumper, 7 | ); 8 | 9 | $s: ( 10 | media: 576px, // min-width 11 | gutter: $bumper-mobile 12 | ); 13 | 14 | $m: ( 15 | media: 768px, // min-width 16 | gutter: $bumper 17 | ); 18 | 19 | $l: ( 20 | media: 992px, // min-width 21 | gutter: $bumper 22 | ); 23 | 24 | $xl: ( 25 | media: 1200px, // min-width 26 | gutter: $bumper 27 | ); 28 | -------------------------------------------------------------------------------- /website/src/assets/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | @import '~bourbon/app/assets/stylesheets/bourbon'; 2 | @import '~bourbon-neat/core/_neat'; 3 | 4 | @mixin align-all($position: 'absolute') { 5 | @include position($position, 50% null null 50%); 6 | transform: translate(-50%, -50%); 7 | } 8 | 9 | @mixin align-reset($position: static) { 10 | @include position($position, auto); 11 | transform: none; 12 | } 13 | 14 | @mixin responsive-wrap($padding-bottom: 56.25%) { 15 | height: 0; 16 | padding-bottom: $padding-bottom; 17 | position: relative; 18 | } 19 | 20 | @mixin svg($width: 20px, $height: 20px, $fill: white) { 21 | @include size($width $height); 22 | 23 | /deep/ svg { 24 | @include size(100%); 25 | display: block; 26 | fill: $fill; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /website/src/assets/scss/_typography.scss: -------------------------------------------------------------------------------- 1 | @import "colors"; 2 | @import "mixins"; 3 | 4 | $poppins: 'Poppins', Helvetica, Arial, sans-serif; 5 | 6 | %body { 7 | font-size: 14px; 8 | font-weight: 500; 9 | line-height: 1; 10 | line-height: normal; 11 | 12 | @include grid-media($m) { 13 | font-size: 18px; 14 | } 15 | } 16 | 17 | %body-m { 18 | @extend %body; 19 | font-size: 16px; 20 | 21 | @include grid-media($m) { 22 | font-size: 20px; 23 | } 24 | 25 | @media (max-height: 850px) and (max-width: 768px) { 26 | font-size: 14px; 27 | } 28 | 29 | @media (max-height: 750px) and (min-width: 768px) { 30 | font-size: 14px; 31 | } 32 | 33 | @media (max-height: 575px) and (max-width: 768px) { 34 | font-size: 12px; 35 | } 36 | } 37 | 38 | %body-l { 39 | @extend %body; 40 | font-size: 16px; 41 | 42 | @include grid-media($m) { 43 | font-size: 28px; 44 | } 45 | 46 | @media (max-height: 700px) and (max-width: 768px) { 47 | font-size: 16px; 48 | } 49 | 50 | @media (max-height: 700px) and (min-width: 768px) { 51 | font-size: 18px; 52 | } 53 | 54 | @media (max-height: 575px) and (max-width: 768px) { 55 | font-size: 14px; 56 | } 57 | } 58 | 59 | %cta { 60 | font-size: 13px; 61 | font-weight: 600; 62 | letter-spacing: $letter-spacing; 63 | text-transform: uppercase; 64 | text-decoration: none; 65 | 66 | @include grid-media($m) { 67 | font-size: 16px; 68 | } 69 | 70 | @include grid-media($l) { 71 | font-size: 20px; 72 | } 73 | } 74 | 75 | %button-outline { 76 | @extend %cta; 77 | @include padding(10px 15px); 78 | border: 2px solid; 79 | border-color: $black; 80 | border-radius: $border-radius; 81 | color: $black; 82 | display: block; 83 | text-align: center; 84 | transition: all $transition-speed; 85 | 86 | /deep/ svg { 87 | fill: $black; 88 | } 89 | 90 | @include grid-media($m) { 91 | @include padding(15px 25px); 92 | background-color: rgba($white, 0.8); 93 | border: none; 94 | } 95 | 96 | &.inverted { 97 | background-color: rgba($white, 0.8); 98 | } 99 | 100 | &:active, 101 | &:focus, 102 | &:hover { 103 | color: $black; 104 | background-color: $white; 105 | 106 | /deep/ svg { 107 | fill: $black; 108 | transition: fill $transition-speed; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /website/src/assets/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // Spacing 2 | $spacing-s: 30px; 3 | $spacing-m: 40px; 4 | $spacing-l: 60px; 5 | $spacing-xl: 100px; 6 | 7 | // Borders 8 | $border-radius: 35px; 9 | $border-radius-l: $border-radius * 2; 10 | 11 | // Typography spacing 12 | $letter-spacing: 0.2em; 13 | 14 | // Transition 15 | $transition-speed: 0.3s; 16 | $transition-delay: 1s; 17 | $transition-ease: cubic-bezier(0.165, 0.840, 0.440, 1.000); 18 | -------------------------------------------------------------------------------- /website/src/assets/scss/shared.scss: -------------------------------------------------------------------------------- 1 | @import '~bourbon/app/assets/stylesheets/bourbon'; 2 | @import '~bourbon-neat/core/_neat'; 3 | @import "colors"; 4 | @import "variables"; 5 | @import "grid"; 6 | @import "typography"; 7 | @import "mixins"; 8 | -------------------------------------------------------------------------------- /website/src/assets/share-jam.html: -------------------------------------------------------------------------------- 1 | Check out this jam I made with MixLab! 2 | -------------------------------------------------------------------------------- /website/src/assets/silence.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecreativelab/mix-lab/997448eeab2a5ef7ce94d89ec0eddd6116bec7aa/website/src/assets/silence.mp3 -------------------------------------------------------------------------------- /website/src/assets/third_party/METADATA: -------------------------------------------------------------------------------- 1 | name: "webrtc-audio-recording" 2 | description: 3 | "A simple audio recorder which works in Safari 11" 4 | 5 | third_party { 6 | url { 7 | type: HOMEPAGE 8 | value: "https://danielstorey.github.io/webrtc-audio-recording/" 9 | } 10 | url { 11 | type: GIT 12 | value: "https://github.com/danielstorey/webrtc-audio-recording/" 13 | } 14 | version: "1.0.0" 15 | last_upgrade_date { year: 2017 month: 10 day: 24 } 16 | license_type: NOTICE 17 | } 18 | -------------------------------------------------------------------------------- /website/src/assets/third_party/webrtc-audio-recording/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 [Daniel Storey](https://github.com/danielstorey/webrtc-audio-recording) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /website/src/assets/third_party/webrtc-audio-recording/README.md: -------------------------------------------------------------------------------- 1 | # Audio Recording Using WebRTC 2 | 3 | This repository demonstrates how it is possible to record and playback audio in most modern browsers, and most notably - Safari 11 on both Mac and IOS. 4 | 5 | #### [Click here](https://danielstorey.github.io/webrtc-audio-recording/) for the demo 6 | 7 |
8 | 9 | You can also serve and work on the files locally but please note this will not work unless the site is hosted using SSL (https://) 10 | 11 | I have included Open SSL certificates for convenience and once you have installed the necessary modules via `npm install` you can simply run `node server` and open `https://localhost:3000` in your browser to view. 12 | 13 |
14 | 15 | The most important thing to note about getting this to work in IOS is that the `AudioContext` must be created within an event handler and not within an automatically running script or a Promise. This is to do with the measures that Apple has put in place to prevent audio from automatically playing when you visit a site. So as long as you call `new AudioContext()` or `new webkitAudioContext()` from within an event handler you'll be fine. 16 | 17 | The other thing to watch out for is to make sure that this context not 'garbage collected', otherwise the audio processor will stop with no error or warning. In this example I have created a `Storage` object in the global scope and assigned the `AudioContext` as a property of this object. 18 | 19 |
20 | 21 | Finally I just want to say that much of my work on this has been based on, (and copied!) from [Muaz Khan's](https://github.com/muaz-khan) rather brilliant [RecordRTC](https://github.com/muaz-khan/RecordRTC) library, which includes video and gif recording as well. 22 | 23 | This is simply a lightweight example of how recording audio can work and not necessarily a reusable library in its current state. -------------------------------------------------------------------------------- /website/src/assets/third_party/webrtc-audio-recording/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebRTC Safari Test 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |
16 | 17 |

Audio Recording using RecordRTC

18 |

Tested in Chrome, Firefox and Safari 11 (Mac and IOS)

19 | 20 |
21 | 22 | 23 | 24 |
25 | 26 |
27 |
28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /website/src/assets/third_party/webrtc-audio-recording/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "safari-audio-recording", 3 | "version": "1.0.0", 4 | "description": "A simple audio recorder which works in Safari 11", 5 | "main": "AudioRecorder.js", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "browser-sync": "^2.18.13" 9 | }, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1", 12 | "start": "node server.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://danstorey@bitbucket.org/danstorey/danstorey.bitbucket.io.git" 17 | }, 18 | "author": "Dan Storey ", 19 | "license": "MIT", 20 | "homepage": "https://github.com/danielstorey/webrtc-audio-recording.git" 21 | } 22 | -------------------------------------------------------------------------------- /website/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export const environment = { 18 | production: true, 19 | //look_up_api_path: 'https://say-to-play.appspot.com/api/' 20 | look_up_api_path: 'https://lookup-dot-say-to-play.appspot.com/' 21 | }; 22 | -------------------------------------------------------------------------------- /website/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // The file contents for the current environment will overwrite these during build. 18 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 19 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 20 | // The list of which env maps to which file can be found in `.angular-cli.json`. 21 | 22 | export const environment = { 23 | production: false, 24 | look_up_api_path: 'https://lookup-dot-say-to-play.appspot.com/' 25 | }; 26 | -------------------------------------------------------------------------------- /website/src/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { enableProdMode } from '@angular/core'; 18 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 19 | import { webcomponentsReady} from '@codebakery/origami'; 20 | 21 | import { AppModule } from './app/app.module'; 22 | import { environment } from './environments/environment'; 23 | 24 | if (environment.production) { 25 | enableProdMode(); 26 | } 27 | 28 | webcomponentsReady().then(() => { 29 | platformBrowserDynamic().bootstrapModule(AppModule, { 30 | enableLegacyTemplate: false 31 | }); 32 | }).catch(error => { 33 | // No WebComponent support and webcomponentsjs is not loaded 34 | console.error(error); 35 | }); 36 | 37 | -------------------------------------------------------------------------------- /website/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * This file includes polyfills needed by Angular and is loaded before the app. 19 | * You can add your own extra polyfills to this file. 20 | * 21 | * This file is divided into 2 sections: 22 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 23 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 24 | * file. 25 | * 26 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 27 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 28 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 29 | * 30 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 31 | */ 32 | 33 | /*************************************************************************************************** 34 | * BROWSER POLYFILLS 35 | */ 36 | 37 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 38 | import 'core-js/es6/symbol'; 39 | import 'core-js/es6/object'; 40 | import 'core-js/es6/function'; 41 | import 'core-js/es6/parse-int'; 42 | import 'core-js/es6/parse-float'; 43 | import 'core-js/es6/number'; 44 | import 'core-js/es6/math'; 45 | import 'core-js/es6/string'; 46 | import 'core-js/es6/date'; 47 | import 'core-js/es6/array'; 48 | import 'core-js/es6/regexp'; 49 | import 'core-js/es6/map'; 50 | import 'core-js/es6/weak-map'; 51 | import 'core-js/es6/set'; 52 | 53 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 54 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 55 | 56 | /** Evergreen browsers require these. **/ 57 | import 'core-js/es6/reflect'; 58 | import 'core-js/es7/reflect'; 59 | 60 | 61 | /** 62 | * Required to support Web Animations `@angular/animation`. 63 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation 64 | **/ 65 | import 'web-animations-js'; // Run `npm install --save web-animations-js`. 66 | 67 | 68 | 69 | /*************************************************************************************************** 70 | * Zone JS is required by Angular itself. 71 | */ 72 | import 'zone.js/dist/zone'; // Included with Angular CLI. 73 | 74 | 75 | 76 | /*************************************************************************************************** 77 | * APPLICATION IMPORTS 78 | */ 79 | 80 | /** 81 | * Date, currency, decimal and percent pipes. 82 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 83 | */ 84 | // import 'intl'; // Run `npm install --save intl`. 85 | /** 86 | * Need to import at least one locale-data with intl. 87 | */ 88 | // import 'intl/locale-data/jsonp/en'; 89 | -------------------------------------------------------------------------------- /website/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @import '~bourbon/app/assets/stylesheets/bourbon'; 3 | @import 'assets/scss/colors'; 4 | 5 | // Fonts 6 | @import url('https://fonts.googleapis.com/css?family=Poppins'); 7 | 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | h1, 15 | h2, 16 | h3, 17 | h4, 18 | h5, 19 | h6 { 20 | font-size: 1em; 21 | font-weight: normal; 22 | -webkit-font-smoothing: antialiased; 23 | margin: 0; 24 | } 25 | 26 | html { 27 | @include prefixer(font-smoothing, antialiased, webkit); 28 | @include prefixer(osx-font-smoothing, grayscale, moz); 29 | @include prefixer(text-size-adjust, 100%, webkit); 30 | user-select: none; 31 | overflow: hidden; 32 | } 33 | 34 | body { 35 | background: $black; 36 | color: $gray; 37 | font-family: 'Poppins', sans-serif; 38 | font-weight: 500; 39 | margin: 0; 40 | } 41 | 42 | ul { 43 | list-style-type: none; 44 | padding: 0; 45 | } 46 | 47 | p { 48 | margin: 0; 49 | } 50 | -------------------------------------------------------------------------------- /website/src/test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 18 | 19 | import 'zone.js/dist/long-stack-trace-zone'; 20 | import 'zone.js/dist/proxy.js'; 21 | import 'zone.js/dist/sync-test'; 22 | import 'zone.js/dist/jasmine-patch'; 23 | import 'zone.js/dist/async-test'; 24 | import 'zone.js/dist/fake-async-test'; 25 | import { getTestBed } from '@angular/core/testing'; 26 | import { 27 | BrowserDynamicTestingModule, 28 | platformBrowserDynamicTesting 29 | } from '@angular/platform-browser-dynamic/testing'; 30 | 31 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 32 | declare const __karma__: any; 33 | declare const require: any; 34 | 35 | // Prevent Karma from running prematurely. 36 | __karma__.loaded = function () {}; 37 | 38 | // First, initialize the Angular testing environment. 39 | getTestBed().initTestEnvironment( 40 | BrowserDynamicTestingModule, 41 | platformBrowserDynamicTesting() 42 | ); 43 | // Then we find all the tests. 44 | const context = require.context('./', true, /\.spec\.ts$/); 45 | // And load the modules. 46 | context.keys().map(context); 47 | // Finally, start Karma to run the tests. 48 | __karma__.start(); 49 | -------------------------------------------------------------------------------- /website/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "es2015", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /website/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "files": [ 14 | "test.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /website/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the 'License'); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an 'AS IS' BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* SystemJS module definition */ 18 | declare var module: NodeModule; 19 | interface NodeModule { 20 | id: string; 21 | } 22 | -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./static/out-tsc", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es5", 11 | "typeRoots": [ 12 | "node_modules/@types" 13 | ], 14 | "lib": [ 15 | "es2017", 16 | "dom" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /website/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "eofline": true, 15 | "forin": true, 16 | "import-blacklist": [ 17 | true, 18 | "rxjs" 19 | ], 20 | "import-spacing": true, 21 | "indent": [ 22 | true, 23 | "spaces" 24 | ], 25 | "interface-over-type-literal": true, 26 | "label-position": true, 27 | "max-line-length": [ 28 | true, 29 | 140 30 | ], 31 | "member-access": false, 32 | "member-ordering": [ 33 | true, 34 | { 35 | "order": [ 36 | "static-field", 37 | "instance-field", 38 | "static-method", 39 | "instance-method" 40 | ] 41 | } 42 | ], 43 | "no-arg": true, 44 | "no-bitwise": true, 45 | "no-console": [ 46 | true, 47 | "debug", 48 | "info", 49 | "time", 50 | "timeEnd", 51 | "trace" 52 | ], 53 | "no-construct": true, 54 | "no-debugger": true, 55 | "no-duplicate-super": true, 56 | "no-empty": false, 57 | "no-empty-interface": true, 58 | "no-eval": true, 59 | "no-inferrable-types": [ 60 | true, 61 | "ignore-params" 62 | ], 63 | "no-misused-new": true, 64 | "no-non-null-assertion": true, 65 | "no-shadowed-variable": true, 66 | "no-string-literal": false, 67 | "no-string-throw": true, 68 | "no-switch-case-fall-through": true, 69 | "no-trailing-whitespace": true, 70 | "no-unnecessary-initializer": true, 71 | "no-unused-expression": true, 72 | "no-use-before-declare": true, 73 | "no-var-keyword": true, 74 | "object-literal-sort-keys": false, 75 | "one-line": [ 76 | true, 77 | "check-open-brace", 78 | "check-catch", 79 | "check-else", 80 | "check-whitespace" 81 | ], 82 | "prefer-const": true, 83 | "quotemark": [ 84 | true, 85 | "single" 86 | ], 87 | "radix": true, 88 | "semicolon": [ 89 | true, 90 | "always" 91 | ], 92 | "triple-equals": [ 93 | true, 94 | "allow-null-check" 95 | ], 96 | "typedef-whitespace": [ 97 | true, 98 | { 99 | "call-signature": "nospace", 100 | "index-signature": "nospace", 101 | "parameter": "nospace", 102 | "property-declaration": "nospace", 103 | "variable-declaration": "nospace" 104 | } 105 | ], 106 | "typeof-compare": true, 107 | "unified-signatures": true, 108 | "variable-name": false, 109 | "whitespace": [ 110 | true, 111 | "check-branch", 112 | "check-decl", 113 | "check-operator", 114 | "check-separator", 115 | "check-type" 116 | ], 117 | "directive-selector": [ 118 | true, 119 | "attribute", 120 | "app", 121 | "camelCase" 122 | ], 123 | "component-selector": [ 124 | true, 125 | "element", 126 | "app", 127 | "kebab-case" 128 | ], 129 | "use-input-property-decorator": true, 130 | "use-output-property-decorator": true, 131 | "use-host-property-decorator": true, 132 | "no-input-rename": true, 133 | "no-output-rename": true, 134 | "use-life-cycle-interface": true, 135 | "use-pipe-transform-interface": true, 136 | "component-class-suffix": true, 137 | "directive-class-suffix": true, 138 | "no-access-missing-member": true, 139 | "templates-use-public": true, 140 | "invoke-injectable": true 141 | } 142 | } 143 | --------------------------------------------------------------------------------