Skip to content

Commit

Permalink
Merge pull request #257 from paulkaplan/sound-library
Browse files Browse the repository at this point in the history
Sound library first iteration
  • Loading branch information
paulkaplan committed Mar 23, 2017
2 parents 588445e + 4c23f42 commit c7d7562
Show file tree
Hide file tree
Showing 7 changed files with 1,169 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/components/library/library.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class LibraryComponent extends React.Component {
// Double select: select as the library's value.
this.props.onRequestClose();
this.props.onItemSelected(this.props.data[id]);
} else {
if (this.props.onItemChosen) {
this.props.onItemChosen(this.props.data[id]);
}
}
this.setState({selectedItem: id});
}
Expand Down Expand Up @@ -61,6 +65,7 @@ LibraryComponent.propTypes = {
})
/* eslint-enable react/no-unused-prop-types, lines-around-comment */
),
onItemChosen: React.PropTypes.func,
onItemSelected: React.PropTypes.func,
onRequestClose: React.PropTypes.func,
title: React.PropTypes.string.isRequired,
Expand Down
1 change: 1 addition & 0 deletions src/components/target-pane/icon--sound-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/components/target-pane/target-pane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const VM = require('scratch-vm');
const Box = require('../box/box.jsx');
const BackdropLibrary = require('../../containers/backdrop-library.jsx');
const CostumeLibrary = require('../../containers/costume-library.jsx');
const SoundLibrary = require('../../containers/sound-library.jsx');
const SpriteLibrary = require('../../containers/sprite-library.jsx');
const SpriteSelectorComponent = require('../sprite-selector/sprite-selector.jsx');
const StageSelector = require('../../containers/stage-selector.jsx');
Expand Down Expand Up @@ -36,6 +37,7 @@ class TargetPane extends React.Component {
editingTarget,
backdropLibraryVisible,
costumeLibraryVisible,
soundLibraryVisible,
spriteLibraryVisible,
onChangeSpriteDraggability,
onChangeSpriteName,
Expand All @@ -48,6 +50,7 @@ class TargetPane extends React.Component {
onNewBackdropClick,
onRequestCloseBackdropLibrary,
onRequestCloseCostumeLibrary,
onRequestCloseSoundLibrary,
onRequestCloseSpriteLibrary,
onSelectSprite,
stage,
Expand Down Expand Up @@ -113,6 +116,11 @@ class TargetPane extends React.Component {
vm={vm}
onRequestClose={onRequestCloseCostumeLibrary}
/>
<SoundLibrary
visible={soundLibraryVisible}
vm={vm}
onRequestClose={onRequestCloseSoundLibrary}
/>
<BackdropLibrary
visible={backdropLibraryVisible}
vm={vm}
Expand Down Expand Up @@ -154,11 +162,14 @@ TargetPane.propTypes = {
onChangeSpriteY: React.PropTypes.func,
onDeleteSprite: React.PropTypes.func,
onNewBackdropClick: React.PropTypes.func,
onNewSoundClick: React.PropTypes.func,
onNewSpriteClick: React.PropTypes.func,
onRequestCloseBackdropLibrary: React.PropTypes.func,
onRequestCloseCostumeLibrary: React.PropTypes.func,
onRequestCloseSoundLibrary: React.PropTypes.func,
onRequestCloseSpriteLibrary: React.PropTypes.func,
onSelectSprite: React.PropTypes.func,
soundLibraryVisible: React.PropTypes.bool,
spriteLibraryVisible: React.PropTypes.bool,
sprites: React.PropTypes.objectOf(spriteShape),
stage: spriteShape,
Expand Down
89 changes: 89 additions & 0 deletions src/containers/sound-library.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const bindAll = require('lodash.bindall');
const React = require('react');
const VM = require('scratch-vm');
const AudioEngine = require('scratch-audio');

const LibaryComponent = require('../components/library/library.jsx');
const soundIcon = require('../components/target-pane/icon--sound-dark.svg');

const soundLibraryContent = require('../lib/libraries/sounds.json');

const md5ToUrl = md5 => (`https://cdn.assets.scratch.mit.edu/internalapi/asset/${md5}/get/`);

class SoundLibrary extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleItemSelected',
'handleItemChosen'
]);
}
componentDidMount () {
// @todo lots of architectural questions here
// - Should the sound library component own an audio player, or use the VM?
// - Should the sound library load up all the sounds or only on demand?
// - How can we get a callback for knowing when the sound has been loaded?
this.audioEngine = new AudioEngine();
this.player = this.audioEngine.createPlayer();
this.audioEngine.loadSounds(soundLibraryContent.map(sound => (
{
fileUrl: md5ToUrl(sound.md5),
...sound
}
)));
}
handleItemChosen (item) {
this.player.playSound(item._md5);
}
handleItemSelected (item) {
// @todo these two props should be handled by a VM.addSound function
const nextSoundId = this.props.vm.editingTarget.sprite.sounds.length;
const fileUrl = md5ToUrl(item._md5);
const vmSound = {
fileUrl,
format: item.format,
md5: item._md5,
rate: item.rate,
sampleCount: item.sampleCount,
soundID: nextSoundId,
name: item.name
};
// @todo awaiting an official VM.addSound function
// it will need to both add to sprite and load the sound
this.props.vm.editingTarget.sprite.sounds.push(vmSound);
this.props.vm.runtime.audioEngine.loadSounds([vmSound]);
}
render () {
// @todo need to use this hack to avoid library using md5 for image
const soundLibraryThumbnailData = soundLibraryContent.map(sound => {
const {
md5,
...otherData
} = sound;
return {
_md5: md5,
rawURL: soundIcon,
...otherData
};
});

return (
<LibaryComponent
data={soundLibraryThumbnailData}
title="Sound Library"
visible={this.props.visible}
onItemChosen={this.handleItemChosen}
onItemSelected={this.handleItemSelected}
onRequestClose={this.props.onRequestClose}
/>
);
}
}

SoundLibrary.propTypes = {
onRequestClose: React.PropTypes.func,
visible: React.PropTypes.bool,
vm: React.PropTypes.instanceOf(VM).isRequired
};

module.exports = SoundLibrary;
10 changes: 10 additions & 0 deletions src/containers/target-pane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ const {connect} = require('react-redux');

const {
openBackdropLibrary,
openSoundLibrary,
openSpriteLibrary,
closeBackdropLibrary,
closeCostumeLibrary,
closeSoundLibrary,
closeSpriteLibrary
} = require('../reducers/modals');

Expand Down Expand Up @@ -87,6 +89,7 @@ const mapStateToProps = state => ({
return sprites;
}, {}),
stage: state.targets.stage,
soundLibraryVisible: state.modals.soundLibrary,
spriteLibraryVisible: state.modals.spriteLibrary,
costumeLibraryVisible: state.modals.costumeLibrary,
backdropLibraryVisible: state.modals.backdropLibrary
Expand All @@ -96,6 +99,10 @@ const mapDispatchToProps = dispatch => ({
e.preventDefault();
dispatch(openBackdropLibrary());
},
onNewSoundClick: e => {
e.preventDefault();
dispatch(openSoundLibrary());
},
onNewSpriteClick: e => {
e.preventDefault();
dispatch(openSpriteLibrary());
Expand All @@ -106,6 +113,9 @@ const mapDispatchToProps = dispatch => ({
onRequestCloseCostumeLibrary: () => {
dispatch(closeCostumeLibrary());
},
onRequestCloseSoundLibrary: () => {
dispatch(closeSoundLibrary());
},
onRequestCloseSpriteLibrary: () => {
dispatch(closeSpriteLibrary());
}
Expand Down
Loading

0 comments on commit c7d7562

Please sign in to comment.