'From Squeak3.5 of ''11 April 2003'' [latest update: #5180] on 25 February 2004 at 9:33:09 pm'! "Change Set: MPEGPlayer-eToyVocabulary-dgd Date: 16 February 2004 Author: Diego Gomez Deck Export the current funcionality in MPEGMorph to eToys environment. The motivation is to improve the 'Active Essay' features of squeak from eToys level. Now you can play, stop and rewind; read/modify the volume and the position; change the repeat option and ask is the move/sound is running. See an example of use at: http://swiki.agro.uba.ar/small_land/uploads/1/video_from_etoys.jpeg "! AlignmentMorph subclass: #MPEGMoviePlayerMorph instanceVariableNames: 'moviePlayer positionSlider volumeSlider ' classVariableNames: '' poolDictionaries: '' category: 'Movies-Player'! !MPEGDisplayMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 21:41'! isRunning "answer whatever the receiver is running" ^ running! ! !MPEGFile methodsFor: 'converting' stamp: 'dgd 2/16/2004 14:19'! convertToSqueakMovieFileNamed: fileName "convert the receiver to a squeak-format movie" " (MPEGFile openFile: '/H/squeak/Small-Land/Demo/media/mazinger_z_spanish_op.mpg') convertToSqueakMovieFileNamed: 'MazingerZ.squeakmovie' " | movieFile max w h d frameBuffer | movieFile := FileStream newFileNamed: fileName. [movieFile binary. "no idea what goes here..." movieFile nextInt32Put: 0. movieFile nextInt32Put: (w := self videoFrameWidth: 0). movieFile nextInt32Put: (h := self videoFrameHeight: 0). "Depth of form data stored" "we really don't know but try to preserve some space" movieFile nextInt32Put: (d := 16). movieFile nextInt32Put: (max := self videoFrames: 0). "min: 100" movieFile nextInt32Put: (1000 * 1000 / (self videoFrameRate: 0)) rounded. "Padding?" movieFile nextPutAll: (ByteArray new: 128 - movieFile position). frameBuffer := Form extent: w @ h depth: d. self videoSetFrame: 1 stream: 0. 'Converting movie...' displayProgressAt: Sensor cursorPoint from: 1 to: max during: [:bar | 1 to: max do: [:i | bar value: i. self videoReadFrameInto: frameBuffer stream: 0. frameBuffer display. movieFile nextInt32Put: i. movieFile nextPutAll: frameBuffer bits]]] ensure: [movieFile close]! ! !MPEGMoviePlayerMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 21:11'! getPosition "answer the receiver's movie position" ^ positionSlider getScaledValue! ! !MPEGMoviePlayerMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 21:53'! getVolume "answer the receiver's movie position" ^ self volumeSlider isNil ifFalse:[self volumeSlider getScaledValue] ifTrue:[0.0]! ! !MPEGMoviePlayerMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 20:23'! guessVolumeSlider "private - look for a morph that is the receiver's volumeSlider" ^ self allMorphs detect: [:each | "first look in my own morphs" each class == SimpleSliderMorph and: [each actionSelector == #volume:]] ifNone: [| w | "second try, look all over the world (if any)" w := self world. w isNil ifFalse: ["" w allMorphs detect: [:each | "" each class == SimpleSliderMorph and: [each actionSelector == #volume:] and: [each target == moviePlayer]] ifNone: []]]! ! !MPEGMoviePlayerMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 21:11'! setPosition: aNumber "changes the receiver's movie position" | newPosition | newPosition := aNumber asFloat min: 1.0 max: 0.0. positionSlider value: newPosition. moviePlayer moviePosition: newPosition! ! !MPEGMoviePlayerMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 21:57'! setVolume: aNumber "changes the receiver's movie position" | newVolume | newVolume := aNumber asFloat min: 1.0 max: 0.0. self volumeSlider isNil ifFalse:[self volumeSlider value: newVolume]. moviePlayer volume: newVolume! ! !MPEGMoviePlayerMorph methodsFor: 'accessing' stamp: 'dgd 2/15/2004 20:13'! volumeSlider "answer the receiver's volumeSlider note: if the instance var is undefined, try to get the sliders from the allMorphs chain. in this way an instance of the receiver created before the instVars was added can works fine" ^ volumeSlider ifNil: [volumeSlider := self guessVolumeSlider]! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 22:11'! defaultFloatPrecisionFor: aGetSelector "Answer a number indicating the default float precision to be used in a numeric readout for which the receiver provides the data. Individual morphs can override this. Showing fractional values for readouts of getCursor was in response to an explicit request from ack" aGetSelector == #getVolume ifTrue: [^ 0.01]. aGetSelector == #getPosition ifTrue: [^ 0.001]. ^ super defaultFloatPrecisionFor: aGetSelector! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 22:03'! getIsRunning "answer whateve the receiver is running" ^ moviePlayer isRunning! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 22:06'! getRepeat "answer whateve the receiver is running" ^ moviePlayer repeat! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 21:30'! play "play the receiver" moviePlayer startPlaying! ]style[(4 2 19 26)f3b,f3,f3c152050000,f3! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 21:31'! rewind "rewind the receiver" moviePlayer rewindMovie! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 22:07'! setRepeat: aBoolean "answer whateve the receiver is running" moviePlayer repeat: aBoolean! ! !MPEGMoviePlayerMorph methodsFor: 'e-toy support' stamp: 'dgd 2/15/2004 21:31'! stop "stop the receiver" moviePlayer stopPlaying! ! !MPEGMoviePlayerMorph methodsFor: 'private' stamp: 'dgd 2/15/2004 20:04'! addVolumeSlider | r | volumeSlider _ SimpleSliderMorph new color: (Color r: 0.71 g: 0.871 b: 1.0); extent: 200@2; target: moviePlayer; actionSelector: #volume:; adjustToValue: 0.5. r _ AlignmentMorph newRow color: Color transparent; layoutInset: 0; wrapCentering: #center; cellPositioning: #leftCenter; hResizing: #shrinkWrap; vResizing: #rigid; height: 24. r addMorphBack: (StringMorph contents: ' soft ' translated). r addMorphBack: volumeSlider. r addMorphBack: (StringMorph contents: ' loud' translated). self addMorphBack: r. ! ! !MPEGMoviePlayerMorph class methodsFor: 'scripting' stamp: 'dgd 2/15/2004 22:08'! additionsToViewerCategories "Answer a list of ( ) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories." ^ #( (playing ( (slot position 'A number representing the current position of the movie/sound.' Number readWrite Player getPosition Player setPosition:) (slot volume 'A number representing the volume of the movie.' Number readWrite Player getVolume Player setVolume:) (command play 'Start playing the movie/sound') (command stop 'Stop playing the movie/sound') (command rewind 'Rewind the movie/sound') (slot isRunning 'Whether the movie/sound is being played' Boolean readOnly Player getIsRunning unused unused) (slot repeat 'Whether the movie/sound will play in an endless loop' Boolean readWrite Player getRepeat Player setRepeat:) ) ))! ! !Player methodsFor: 'slot getters/setters' stamp: 'dgd 2/15/2004 21:11'! getPosition "Answer the numeric value contained in my costume" ^ costume renderedMorph getPosition! ! !Player methodsFor: 'slot getters/setters' stamp: 'dgd 2/15/2004 21:13'! getVolume "Answer the numeric value contained in my costume" ^ costume renderedMorph getVolume! ! !Player methodsFor: 'slot getters/setters' stamp: 'dgd 2/15/2004 21:11'! setPosition: amt "Set the receiver's numeric value to the amount. This is passed on to the costume" costume renderedMorph setPosition: amt! ! !Player methodsFor: 'slot getters/setters' stamp: 'dgd 2/15/2004 21:15'! setVolume: amt "Set the receiver's numeric value to the amount. This is passed on to the costume" costume renderedMorph setVolume: amt! ! !Player methodsFor: 'playing commands' stamp: 'dgd 2/15/2004 22:03'! getIsRunning ^ self sendMessageToCostume: #getIsRunning! ! !Player methodsFor: 'playing commands' stamp: 'dgd 2/15/2004 22:06'! getRepeat ^ self sendMessageToCostume: #getRepeat! ! !Player methodsFor: 'playing commands' stamp: 'dgd 2/15/2004 21:29'! play self sendMessageToCostume: #play! ! !Player methodsFor: 'playing commands' stamp: 'dgd 2/15/2004 21:32'! rewind self sendMessageToCostume: #rewind! ! !Player methodsFor: 'playing commands' stamp: 'dgd 2/15/2004 22:07'! setRepeat: aBoolean self sendMessageToCostume: #setRepeat: with: aBoolean! ! !Player methodsFor: 'playing commands' stamp: 'dgd 2/15/2004 21:31'! stop self sendMessageToCostume: #stop! ! Player removeSelector: #isRunning! MPEGMoviePlayerMorph removeSelector: #isRunning! !MPEGMoviePlayerMorph reorganize! ('*Tools-FileList-accessing' moviePlayer) ('accessing' getPosition getVolume guessVolumeSlider setPosition: setVolume: volumeSlider) ('drawing' drawOn:) ('e-toy support' defaultFloatPrecisionFor: getIsRunning getRepeat play rewind setRepeat: stop) ('initialization' initialize) ('menu' invokeMenu) ('stepping' step stepTime) ('private' addButtonRow addPositionSlider addQuitButton addVolumeSlider buttonFillStyle buttonName:action: moviePlayerFillStyle quit) ! !MPEGFile reorganize! ('access' endianness fileHandle fileName getPercentage getTOC:doStreams: getTimeCode seekPercentage: setMMX:) ('audio' audioChannels: audioGetSample: audioPlayerForChannel: audioReReadBuffer:stream:channel: audioReReadBuffer:stream:channel:samples: audioReadBuffer:stream:channel: audioReadBuffer:stream:channel:samples: audioSampleRate: audioSamples: audioSetSample:stream: endOfAudio: hasAudio totalAudioStreams) ('converting' convertToSqueakMovieFileNamed:) ('file ops' finalize) ('initialize-release' closeFile initialize openFile:) ('primitives' primAudioChannels:stream: primAudioReReadBuffer:buffer:channel:samples:stream: primAudioReadBuffer:buffer:channel:samples:stream: primAudioSamples:stream: primDropFrame:frame:stream: primEndOfAudio:stream: primEndOfVideo:stream: primFileClose: primFileOpen: primFrameRate:stream: primGenerateToc:useSearch:doStreams:buffer: primGetFrame:stream: primGetPercentage: primGetSample:stream: primGetTime: primHasAudio: primHasVideo: primPreviousFrame:stream: primSampleRate:stream: primSeekPercentage:percentage: primSetCPUs:number: primSetFrame:frame:stream: primSetMMX:useMMX: primSetSample:sample:stream: primTotalAudioStreams: primTotalVideoStreams: primVideoFrames:stream: primVideoHeight:stream: primVideoReadNextFrameFor:into:x:y:width:height:outWidth:outHeight:colorModel:stream:bytesPerRow: primVideoWidth:stream:) ('video' endOfVideo: hasVideo totalVideoStreams videoDropFrames:stream: videoFrameHeight: videoFrameRate: videoFrameWidth: videoFrames: videoGetFrame: videoPreviousFrame: videoReadFrameInto:stream: videoReadNextFrameInto:x:y:width:height:outWidth:outHeight:colorModel:stream:bytesPerRow: videoSetCPUs: videoSetFrame:stream:) ('private' register unregister) !