View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Case Final Project Summer 2007

DBMM-Milestone 4

Design:


The success of this project highly depended on a robust and flexible design from the earlier milestones. Luckily for us, we implemented a flexible system that allowed the adding of any MovieItem (items that shared similar attributes such as a start time, end time, filename, and location and similar functionalities such as being able to activate its self and deactivate its self) to our MovieItemCollection class. Then to accommodate different file types, we could subclass the MovieItem class and add any additional functionalities that we might need to the subclass. In our previous milestones, users could only add Picture items to the movie. The Picture class was a subclass of the MovieItem class that stored a Morph (Squeak specific object that is used for displaying/undisplaying bitmaps) in addition to the standard MovieItem attributes and knew how to display itself and remove itself from the MovieScreen. In this milestone, users would be able to add mpeg movies, wav and midi sounds, and text to the movie. To satisfy these requirements, we added four new subclasses to the MovieItem class: MIDISequence, WAVSound, MPEGMovie, and MovieText.

File Types Implementation:

MIDI
MIDISequence

We had to make sure we could do several things with a midi sound in order for it to work as a movie component.

Reading In a MIDI File:

In Squeak, there are two things you need to accomplish this. First of all you need to read the contents of a midi file into a score. To do this you must pass in the path of the midi file to the class method scoreFromFileNamed: method in the MIDIFileReader class. Secondly, you need to create a ScorePlayer object that has a reference to the score we just created. The code to do this looks something like the following two lines:

score:=MIDIFileReader scoreFromFileNamed: myfilename.
player:=ScorePlayer onScore: score.



Playing a MIDI File:

Once we have our player up and running, playing the midi file is as easy as calling resumePlaying on the instance of the ScorePlayer class:

player resumePlaying.

Pausing a MIDI File:

Also as easy as calling one method:

player pause.

Rewinding a MIDI File:

Also as easy as calling one method:

player rewind.

Getting the end time of a MIDI File:
This was a rather daunting task, but we needed to know when the sound was over as to tell when the movie was over if the last object being played was a midi sound.

To accomplish this we had to use the ScorePlayer instance (stored in player) and several of its methods. We also used the start time specified by the user in the calculation of the end time. Below is the code:

stopTime:= ( ( ((60.0 / (player tempo * player rate * player score ticksPerQuarterNote)) * ( player durationInTicks)) + 0.999) truncated ) + startTime.

The Coweb was extremely helpful for this, as we actually found the code on there. Without it, we most likely would not have been able to come up with a accurate value. Though some other methods seemed more immediately intuitive, the values that they gave often were incorrect by a significant margin, somtimes as much as a minute.

After we figured out how to do all of this, we added a score attribute and a player attribute to the MIDISequence class and wrote methods for activating the object (playing it), deactivating it (stopping and resetting it), and pausing it.

WAV
WAVSound

Here are a few things we figured out about WAVs in Squeak:

Reading in a WAV from a file:

In Squeak, a WAV is a type of SampledSound. In order to read a WAV file, all you have to do is create a SampledSound object using the class method fromWaveFileNamed:

Here is the code to do this:

sample:=SampledSound fromWaveFileNamed: filename.

Playing a WAV:

As easy as calling a method in the instance of the SampledSound class.

sample play.

Stopping a WAV:

In order to do this you must first pause the WAV and then reset it.

sample pause.
sample reset.


Calculating the end time for a WAV:

Once again we had to calculate the end time:

stopTime:=(((sample duration) + 0.999) truncated) + startTime.

After discovering these capabilities we added a sample attribute to our WAVSound class and methods that allowed us to activate it (play it) and deactivate it (pause then reset it).

MPEG
MPEGMovie

Squeak has many different classes that can be used to manipulate MPEGS. For this project, the one that we found most useful was the MPEGDisplayMorph class. This was an optimal choice because it had built in methods for displaying and undisplaying a MPEG movie.

Reading in a MPEG:

To accomplish this, we first created an instance of the MPEGDisplayMorph class and then called the instance method openFileNamed: passing it the path of the file:

aMPEGDisplayMorph:= MPEGDisplayMorph new.
aMPEGDisplayMorph openFileNamed: (myfilename).


Playing a MPEG:

aMPEGDisplayMorph startPlaying.

Stopping a MPEG:

To do this we call stop on the display morph instance and then rewind it.

aMPEGDisplayMorph stopPlaying.
aMPEGDisplayMorph rewindMovie.


Pausing a MPEG:

To do this we merely stop the mpeg and do not rewind it.

aMPEGDisplayMorph stopPlaying.


Displaying a MPEG:

In our movie we had one large morph that represented the screen of our movie. To display a MPEG all you have to do is add the MPEGDisplayMorph instance to your screen:

myScreen addMorph: aMPEGDisplayMorph.

Undisplaying a MPEG:

To do this, you merely have to call the delete method on the instance of the MPEGDisplayMorph:

aMPEGDisplayMorph delete.

We used the previous information to form our MPEGMovie class that contained an an aMPEGDisplayMorph attribute and methods for activating (playing and displaying a mpeg), deactivating (stopping and undisplaying a mpeg), and pausing a MPEGMovie object.

Text
MovieText>

Text was a fairly easy thing to implement. One awkward thing about text is that it didn't have a filename, so we just initialized it with a dummy value so that it was clear that there was none. The acceptance of a text message was done through the GUI. The user would type in the message he/she wanted and then the text field of the MovieText would be filled with the accepted text. Displaying and undisplaying of the text was similar to the displaying/undisplaying of a mpeg movie with a slight twist. In order to make this work, we stored an instance of a PluggableTextMorph in our MovieText class that had its #text: message on the text accessor within the MovieText class. To display the desired text, all we would do is call the #addMorph: message of the movie's screen morph on the PluggableTextMorph instance:

aScreen addMorph: aPluggableTextMorph.

To undispay text all we had to do was call delete on the PluggableTextMorph instance:

aPluggableTextMorph delete.


Conclusion:


One of the main things our group learned from this milestone is that if you want to get something difficult done, the odds are that there is a class in Squeak that has it done for you already. Also, we learned that a flexible and modular design is very important. If we had not had the foresight to accommodate different types of MovieItems, we would have spent much time and effort on redesigning our program.

Link to this Page