'From etoys2.2 of 24 September 2007 [latest update: #1719] on 20 October 2007 at 5:37:09 pm'!"Change Set:		anonymousSound-swDate:			20 October 2007Author:			Scott Wallace, Karl RambergHandle a drop of an external sound file by opening an AnonymousSoundMorph, allowing the user to play the sound, drop it into a piano roll or an event roll, and also offering the option to add the sound to the sound library.The AnonymousSoundMorphs obtained from the 'hand me a sound token' menu item in the Sound Recorder's menu are now also of the same expanded sort, which is to say, they show a prospective name for the sound, and provide controls to play, stop, and save. When deployed inside a PianoRoll, AnonymousSoundMorphs slim down to dimensions and proportions appropriate for the Piano Roll.  When/if returned to the desktop, they flesh out to their full form with button controls."!AbstractMediaEventMorph subclass: #AnonymousSoundMorph	instanceVariableNames: 'sound interimName '	classVariableNames: ''	poolDictionaries: ''	category: 'Sound-Interface'!!AnonymousSoundMorph commentStamp: 'sw 10/19/2007 16:56' prior: 0!Holds a free-standing sound, i.e. one not associated with the system's sound library.Can be played by hitting Play button, and can stop its playing by hitting Stop.Can be dropped into a piano roll or into an event rollCan also be named and added to the system sound library, by hitting the save button.!!AnonymousSoundMorph methodsFor: 'initialization' stamp: 'sw 10/19/2007 19:13'!addButtonRow	"Add the row of control buttons."	| row button |	row := AlignmentMorph newRow vResizing: #shrinkWrap;				 color: Color transparent.	row addVariableTransparentSpacer.	button := SimpleButtonMorph new label: 'Play' translated font: ScriptingSystem fontForEToyButtons;				 target: self;				 actionSelector: #playSound.	row addMorphBack: button.	row addVariableTransparentSpacer.	button := SimpleButtonMorph new label: 'Stop' translated font: ScriptingSystem fontForEToyButtons;				 target: self;				 actionSelector: #stopSound.	row addMorphBack: button.	row addVariableTransparentSpacer.	button := SimpleButtonMorph new label: 'Save' translated font: ScriptingSystem fontForEToyButtons;				 target: self;				 actionSelector: #addToSoundLibrary .	row addMorphBack: button.	row addVariableTransparentSpacer.	self addMorphBack: row! !!AnonymousSoundMorph methodsFor: 'initialization' stamp: 'sw 10/19/2007 14:50'!initialize	"initialize the state of the receiver"	super initialize.	self height: 18.	self balloonTextSelector: #soundMorphHelpString.	self on: #doubleClick send: #playSound to: self.	self on: #mouseMove send: #openInHand to: self.	self on: #click send: #stopSound to: self.	interimName := SampledSound unusedSoundNameLike: 'Unnamed' translated! !!AnonymousSoundMorph methodsFor: 'initialization' stamp: 'sw 10/19/2007 16:57'!sound: aSampledSound interimName: anInterimName	"Establish the sound object and an interim name."	| aStringMorph |	self removeAllMorphs.	self hResizing: #shrinkWrap; vResizing: #shrinkWrap.	borderWidth _ 2.	self listDirection: #topToBottom.	sound := aSampledSound.	interimName := anInterimName.	aStringMorph := StringMorph contents: interimName font: ScriptingSystem fontForEToyButtons.	self addMorphBack: aStringMorph.	self addButtonRow.	self balloonTextSelector: #soundMorphHelpString.	self setNameTo: interimName! !!AnonymousSoundMorph methodsFor: 'piano roll' stamp: 'sw 10/19/2007 16:30'!justDroppedIntoPianoRoll: newOwner event: evt	"The receiver was just dropped into a piano roll... respond accordingly."	| startX lengthInTicks endX |	super justDroppedIntoPianoRoll: newOwner event: evt.	submorphs size > 1 ifTrue: [submorphs last delete].	self hResizing: #rigid; clipSubmorphs: true.	startTimeInScore _ newOwner timeForX: self left.	lengthInTicks _ newOwner scorePlayer ticksForMSecs: sound duration * 1000.0.	endTimeInScore _ startTimeInScore + lengthInTicks.	endTimeInScore > newOwner scorePlayer durationInTicks ifTrue:		[newOwner scorePlayer updateDuration].	startX _ newOwner xForTime: startTimeInScore.	endX _ newOwner xForTime: endTimeInScore.	self width: endX - startX! !!AnonymousSoundMorph methodsFor: 'piano roll' stamp: 'sw 10/19/2007 16:31'!justDroppedInto: aMorph event: evt	"The receiver was just dropped into some container... respond accordingly."	super justDroppedInto: aMorph event: evt.	(aMorph isKindOf: PianoRollScoreMorph ) ifTrue: [^ self].	submorphs size < 2 ifTrue:		[self sound: sound interimName: interimName]! !!AnonymousSoundMorph methodsFor: 'menu' stamp: 'sw 10/19/2007 15:10'!addCustomMenuItems: aMenu hand: aHandMorph	"Add morph-specific items to the given menu which was invoked by the given hand.  This method provides is invoked both from the halo-menu and from the control-menu regimes."	super addCustomMenuItems: aMenu hand: aHandMorph.	aMenu addTranslatedList: #(		-		('wave editor' openWaveEditorOnSound 'open a wave-editor tool with this sound as its iniital sound')) translatedNoop! !!AnonymousSoundMorph methodsFor: 'menu' stamp: 'sw 10/19/2007 16:34'!addToSoundLibrary	"Add the receiver's sound to the library, and hand the user a tile representing it."	| aName tile |	aName := FillInTheBlank request: 'kindly give the sound a name: ' initialAnswer: (interimName ifNil: ['']).	aName isEmptyOrNil ifTrue: [^ self].	aName := SampledSound unusedSoundNameLike:  aName.	SampledSound			addLibrarySoundNamed: aName			samples: sound samples			samplingRate: sound samplingRate.	tile _ SoundTile new literal: aName.	tile bounds: tile fullBounds.	tile center: self fullBoundsInWorld center.	(ScriptingTileHolder around: tile) center:  self fullBoundsInWorld center;		openInWorld.		self delete! !!AnonymousSoundMorph methodsFor: 'menu' stamp: 'sw 10/19/2007 15:11'!openWaveEditorOnSound	"Open a wave-editor tool on the receiver's sound"	WaveEditor openOn: sound samples! !!AnonymousSoundMorph methodsFor: 'menu' stamp: 'sw 10/18/2007 22:15'!stopPlayingSound	"If the receiver's sound is playing, stop it."	sound pause! !!AnonymousSoundMorph class methodsFor: 'fileIn/Out' stamp: 'sw 10/19/2007 15:18'!fileReaderServicesForFile: fullName suffix: suffix 	"Answer the file services associated with given file"	^ (self registeredAudioFileSuffixes includes: suffix)		ifTrue: [self services]		ifFalse: [#()]! !!AnonymousSoundMorph class methodsFor: 'fileIn/Out' stamp: 'sw 10/19/2007 19:27'!fromFileName: fullName	"Create an instance of the receiver from the given file path."		| newPlayer aSound ext aName |	newPlayer _ self new initialize.	('*aif' match: fullName) 		ifTrue: [aSound := SampledSound fromAIFFfileNamed: fullName].	('*wav' match: fullName) 		ifTrue: [aSound := SampledSound fromWaveFileNamed: fullName].	newPlayer := self new.	ext := FileDirectory extensionFor: fullName.	aName :=  (FileDirectory on: fullName) pathParts last.	ext size > 0 ifTrue:		[aName := aName copyFrom: 1 to: (aName size - (ext size + 1))].		newPlayer sound: aSound interimName: aName.	newPlayer openInWorld! !!AnonymousSoundMorph class methodsFor: 'file suffixes' stamp: 'sw 10/19/2007 15:17'!registeredAudioFileSuffixes    "Answer the file extensions for which the receiver registers audio services with FileList."     "AnonymousSoundMorph registeredAudioFileSuffixes"     ^ { 'aif'.  'wav'}! !!RecordingControls methodsFor: 'private' stamp: 'sw 10/20/2007 02:23'!makeSoundMorph	"Hand the user an anonymous-sound object  representing the receiver's sound."	| m aName |	recorder verifyExistenceOfRecordedSound ifFalse: [^ self].	recorder pause.	recordingSaved := true.	m _ AnonymousSoundMorph new.	m sound: recorder recordedSound interimName: (aName :=  'Unnamed Sound').	m setNameTo: aName.	ActiveHand attachMorph: m! !AnonymousSoundMorph removeSelector: #makeAppearanceReflectSound!AnonymousSoundMorph removeSelector: #sound:!AbstractMediaEventMorph subclass: #AnonymousSoundMorph	instanceVariableNames: 'sound interimName'	classVariableNames: ''	poolDictionaries: ''	category: 'Sound-Interface'!"Postscript:"FileList initialize.!