kopia lustrzana https://github.com/backface/turtlestitch
commit
c346ef43d7
286
gui.js
286
gui.js
|
@ -2296,6 +2296,22 @@ IDE_Morph.prototype.newCamSprite = function () {
|
|||
camDialog.popUp(this.world());
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.recordNewSound = function () {
|
||||
var soundRecorder,
|
||||
myself = this;
|
||||
|
||||
soundRecorder = new SoundRecorderDialogMorph(
|
||||
function (sound) {
|
||||
if (sound) {
|
||||
myself.currentSprite.addSound(sound, myself.newSoundName('recording'));
|
||||
myself.spriteBar.tabBar.tabTo('sounds');
|
||||
myself.hasChangedMedia = true;
|
||||
}
|
||||
});
|
||||
|
||||
soundRecorder.popUp(this.world());
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.duplicateSprite = function (sprite) {
|
||||
var duplicate = sprite.fullCopy();
|
||||
duplicate.setPosition(this.world().hand.position());
|
||||
|
@ -2346,17 +2362,37 @@ IDE_Morph.prototype.removeSprite = function (sprite) {
|
|||
this.selectSprite(this.currentSprite);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.newSoundName = function (name) {
|
||||
var lastSound =
|
||||
this.currentSprite.sounds.at(
|
||||
this.currentSprite.sounds.length());
|
||||
|
||||
return this.newName(
|
||||
lastSound.name || name,
|
||||
this.currentSprite.sounds.asArray().map(
|
||||
function (eachSound) {
|
||||
return eachSound.name;
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.newSpriteName = function (name, ignoredSprite) {
|
||||
var ix = name.indexOf('('),
|
||||
stem = (ix < 0) ? name : name.substring(0, ix),
|
||||
count = 1,
|
||||
newName = stem,
|
||||
all = this.sprites.asArray().concat(this.stage).filter(
|
||||
var all = this.sprites.asArray().concat(this.stage).filter(
|
||||
function (each) {return each !== ignoredSprite; }
|
||||
).map(
|
||||
function (each) {return each.name; }
|
||||
);
|
||||
while (contains(all, newName)) {
|
||||
return this.newName(name, all)
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.newName = function (name, elements) {
|
||||
var ix = name.indexOf('('),
|
||||
stem = (ix < 0) ? name : name.substring(0, ix),
|
||||
count = 1,
|
||||
newName = stem;
|
||||
|
||||
while (contains(elements, newName)) {
|
||||
count += 1;
|
||||
newName = stem + '(' + count + ')';
|
||||
}
|
||||
|
@ -8114,7 +8150,7 @@ SoundIconMorph.prototype.renameSound = function () {
|
|||
|
||||
SoundIconMorph.prototype.removeSound = function () {
|
||||
var jukebox = this.parentThatIsA(JukeboxMorph),
|
||||
idx = this.parent.children.indexOf(this);
|
||||
idx = this.parent.children.indexOf(this + 1);
|
||||
jukebox.removeSound(idx);
|
||||
};
|
||||
|
||||
|
@ -8183,7 +8219,9 @@ JukeboxMorph.prototype.updateList = function () {
|
|||
oldFlag = Morph.prototype.trackChanges,
|
||||
icon,
|
||||
template,
|
||||
txt;
|
||||
txt,
|
||||
ide = this.sprite.parentThatIsA(IDE_Morph),
|
||||
recordButton;
|
||||
|
||||
this.changed();
|
||||
oldFlag = Morph.prototype.trackChanges;
|
||||
|
@ -8204,7 +8242,31 @@ JukeboxMorph.prototype.updateList = function () {
|
|||
txt.setColor(SpriteMorph.prototype.paletteTextColor);
|
||||
txt.setPosition(new Point(x, y));
|
||||
this.addContents(txt);
|
||||
y = txt.bottom() + padding;
|
||||
|
||||
recordButton = new PushButtonMorph(
|
||||
ide,
|
||||
'recordNewSound',
|
||||
new SymbolMorph('circleSolid', 15),
|
||||
);
|
||||
recordButton.padding = 0;
|
||||
recordButton.corner = 12;
|
||||
recordButton.color = IDE_Morph.prototype.groupColor;
|
||||
recordButton.highlightColor = IDE_Morph.prototype.frameColor.darker(50);
|
||||
recordButton.pressColor = recordButton.highlightColor;
|
||||
recordButton.labelMinExtent = new Point(36, 18);
|
||||
recordButton.labelShadowOffset = new Point(-1, -1);
|
||||
recordButton.labelShadowColor = recordButton.highlightColor;
|
||||
recordButton.labelColor = TurtleIconMorph.prototype.labelColor;
|
||||
recordButton.contrast = this.buttonContrast;
|
||||
recordButton.drawNew();
|
||||
recordButton.hint = 'Record a new sound';
|
||||
recordButton.fixLayout();
|
||||
recordButton.label.setColor(new Color(255, 20, 20));
|
||||
recordButton.setPosition(txt.bottomLeft().add(new Point(0, padding * 2)));
|
||||
|
||||
this.addContents(recordButton);
|
||||
|
||||
y = recordButton.bottom() + padding;
|
||||
|
||||
this.sprite.sounds.asArray().forEach(function (sound) {
|
||||
template = icon = new SoundIconMorph(sound, template);
|
||||
|
@ -8674,3 +8736,209 @@ CamSnapshotDialogMorph.prototype.close = function () {
|
|||
}
|
||||
CamSnapshotDialogMorph.uber.destroy.call(this);
|
||||
};
|
||||
|
||||
// SoundRecorderDialogMorph ////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
I am a dialog morph that lets users record sound snippets for their
|
||||
sprites or Stage.
|
||||
*/
|
||||
|
||||
// SoundRecorderDialogMorph inherits from DialogBoxMorph:
|
||||
|
||||
SoundRecorderDialogMorph.prototype = new DialogBoxMorph();
|
||||
SoundRecorderDialogMorph.prototype.constructor = SoundRecorderDialogMorph;
|
||||
SoundRecorderDialogMorph.uber = DialogBoxMorph.prototype;
|
||||
|
||||
// SoundRecorderDialogMorph instance creation
|
||||
|
||||
function SoundRecorderDialogMorph(onAccept) {
|
||||
this.init(onAccept);
|
||||
}
|
||||
|
||||
SoundRecorderDialogMorph.prototype.init = function (onAccept) {
|
||||
var myself = this;
|
||||
this.padding = 10;
|
||||
this.accept = onAccept;
|
||||
|
||||
this.mediaRecorder = null; // an HTML5 MediaRecorder object
|
||||
this.audioElement = document.createElement('audio');
|
||||
this.audioElement.hidden = true;
|
||||
this.audioElement.onended = function (event) {
|
||||
myself.stop();
|
||||
};
|
||||
document.body.appendChild(this.audioElement);
|
||||
|
||||
this.recordButton = null;
|
||||
this.stopButton = null;
|
||||
this.playButton = null;
|
||||
this.progressBar = new BoxMorph();
|
||||
|
||||
SoundRecorderDialogMorph.uber.init.call(this);
|
||||
this.labelString = 'Sound Recorder';
|
||||
this.createLabel();
|
||||
this.buildContents();
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.buildContents = function () {
|
||||
var myself = this,
|
||||
audioChunks = [];
|
||||
|
||||
this.recordButton = new PushButtonMorph(
|
||||
this,
|
||||
'record',
|
||||
new SymbolMorph('circleSolid', 10)
|
||||
);
|
||||
this.recordButton.drawNew();
|
||||
this.recordButton.fixLayout();
|
||||
|
||||
this.stopButton = new PushButtonMorph(
|
||||
this,
|
||||
'stop',
|
||||
new SymbolMorph('rectangleSolid', 10)
|
||||
);
|
||||
this.stopButton.drawNew();
|
||||
this.stopButton.fixLayout();
|
||||
|
||||
this.playButton = new PushButtonMorph(
|
||||
this,
|
||||
'play',
|
||||
new SymbolMorph('pointRight', 10)
|
||||
);
|
||||
this.playButton.drawNew();
|
||||
this.playButton.fixLayout();
|
||||
|
||||
this.buildProgressBar();
|
||||
|
||||
this.addBody(new AlignmentMorph('row', this.padding));
|
||||
this.body.add(this.recordButton);
|
||||
this.body.add(this.stopButton);
|
||||
this.body.add(this.playButton);
|
||||
this.body.add(this.progressBar);
|
||||
|
||||
this.body.fixLayout();
|
||||
|
||||
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
||||
navigator.mediaDevices.getUserMedia({ audio: true })
|
||||
.then(function (stream) {
|
||||
myself.mediaRecorder = new MediaRecorder(stream);
|
||||
myself.mediaRecorder.ondataavailable = function (event) {
|
||||
audioChunks.push(event.data);
|
||||
};
|
||||
myself.mediaRecorder.onstop = function (event) {
|
||||
myself.audioElement.src =
|
||||
window.URL.createObjectURL(
|
||||
new Blob(
|
||||
audioChunks,
|
||||
{'type': 'audio/ogg; codecs=opus'}
|
||||
)
|
||||
);
|
||||
myself.audioElement.load();
|
||||
audioChunks = [];
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
this.addButton('ok', 'Save');
|
||||
this.addButton('cancel', 'Cancel');
|
||||
|
||||
this.fixLayout();
|
||||
this.drawNew();
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.buildProgressBar = function () {
|
||||
var line = new Morph(),
|
||||
myself = this;
|
||||
|
||||
this.progressBar.setExtent(new Point(150, 20));
|
||||
this.progressBar.setColor(new Color(200, 200, 200));
|
||||
this.progressBar.setBorderWidth(1);
|
||||
this.progressBar.setBorderColor(new Color(150, 150, 150));
|
||||
|
||||
line.setExtent(new Point(130, 2));
|
||||
line.setColor(new Color(50, 50, 50));
|
||||
line.setCenter(this.progressBar.center());
|
||||
this.progressBar.add(line);
|
||||
|
||||
this.progressBar.indicator = new Morph();
|
||||
this.progressBar.indicator.setExtent(new Point(5, 15));
|
||||
this.progressBar.indicator.setColor(new Color(50, 200, 50));
|
||||
this.progressBar.indicator.setCenter(line.leftCenter());
|
||||
|
||||
this.progressBar.add(this.progressBar.indicator);
|
||||
|
||||
this.progressBar.setPercentage = function (percentage) {
|
||||
this.indicator.setLeft(
|
||||
line.left() +
|
||||
(line.width() / 100 * percentage) -
|
||||
this.indicator.width() / 2)
|
||||
};
|
||||
|
||||
this.progressBar.step = function () {
|
||||
if (myself.audioElement.duration) {
|
||||
this.setPercentage(
|
||||
myself.audioElement.currentTime /
|
||||
myself.audioElement.duration * 100);
|
||||
} else {
|
||||
this.setPercentage(0);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.record = function () {
|
||||
this.mediaRecorder.start();
|
||||
this.recordButton.label.setColor(new Color(255, 0, 0));
|
||||
this.playButton.label.setColor(new Color(0, 0, 0));
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.stop = function () {
|
||||
var myself = this;
|
||||
|
||||
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
|
||||
this.mediaRecorder.stop();
|
||||
}
|
||||
|
||||
this.audioElement.pause();
|
||||
this.audioElement.currentTime = 0;
|
||||
|
||||
this.recordButton.label.setColor(new Color(0, 0, 0));
|
||||
this.playButton.label.setColor(new Color(0, 0, 0));
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.play = function () {
|
||||
this.stop();
|
||||
this.audioElement.oncanplaythrough = function () {
|
||||
this.play();
|
||||
this.oncanplaythrough = nop;
|
||||
}
|
||||
this.playButton.label.setColor(new Color(0, 255, 0));
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.ok = function () {
|
||||
var myself = this;
|
||||
this.stop();
|
||||
this.audioElement.oncanplaythrough = function () {
|
||||
if (this.duration && this.duration !== Infinity) {
|
||||
myself.accept(this);
|
||||
this.oncanplaythrough = nop;
|
||||
myself.destroy();
|
||||
} else {
|
||||
// For some reason, we need to play the sound
|
||||
// at least once to get its duration.
|
||||
myself.buttons.children.forEach(function (button) {
|
||||
button.disable();
|
||||
});
|
||||
this.play();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
SoundRecorderDialogMorph.prototype.destroy = function () {
|
||||
this.stop();
|
||||
this.audioElement.remove();
|
||||
if (this.mediaRecorder) {
|
||||
this.mediaRecorder.stream.getTracks()[0].stop();
|
||||
}
|
||||
SoundRecorderDialogMorph.uber.destroy.call(this);
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue