View this PageEdit this Page (locked)Attachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

Doug Powers

My name is Doug and this is my Who's Who Page. I really don't have much to say about myself, so I decided that our group could just use this page as a small case study for our mp3 player. For more information about me, visit my web site.

General Info
Group Name:Too Embarassing to Tell
Members:Doug Powers
Dmitri Alerovich
Bryan Kennedy
Andrew Hilton
App Name:Squeak+WinAmp=SqueAmp
Current Version:SqueAmp v0.7



The SqueAmp User Interface

The Status Bar — SqueAmp often 'pauses' when attempting to perform operations such as downloading songs. Thus, we thought it would be wise to have a status bar. The status bar indicates which song is currently playing, whether or not the player is stopped or not, whether or not the next song is being downloaded, and whether or not a search is being formed.

Two Windows — We chose to go with two windows for a couple of reasons. First, we were modeling our UI after the ever so popular WinAmp. Second, the playlist can take up a lot of desktop space, so we wanted the user to be able to optionally close the playlist without closing the player. We were careful to ensure that closing the player would also close the playlist. However, we overlooked the fact that there was no way to reopen the playlist if it had been closed :-(

The Buttons — What, did you expect to find something? I feel the buttons are pretty self explanatory so I won't go into detail about them here.


See squeamp for more on the UI



Playing over the web

To play our songs over the web, we chose to use an applet that harnessed the power of JMF (Java Media Framework). We chose to take this route for the following reasons:
1) It was an object oriented approach.
2) It was portable to any platform JAVA had been ported to.
3) It worked for all types of standard media including video
streams.
4) It works in any browser that supports JAVA Applets
IE, Netscape, Mozilla... just to name a few
5) It would stream the songs rather than require the entire
song to be downloaded first.
6) Olin offered Extra Credit for a JAVA Applet based solution :-)

You can download our applet here: streamingplayerapplet.class


Object Oriented Design

Here is our UML Class Diagram. I won't go into detail about our design here since it's discussed throughout this document.
Uploaded Image: p7.jpg


Handling Multiple users

At the time when we were originally designing the P4 milestone, there had been no clarifications on whether the system would have to support multiple users being able to use the Web-based JukeBox simultaneously.

So we decided to play on the safe side and create a flexible design to handle that requirement. And after many hours of heated deliberations in the TA lab, we finally came up with a neat design (which we later implemented) that efficiently solves the problem of not having unique identification system on the web in a browser-independent way. Here is how we did it:

1. We created an additional class, called JukeBoxCollection (extends Dictionary), which is really a hashtable of JukeBox instances, which stores the current state of the user, such as their playlist.
2. Whenever a user accesses our primary page for the first time, they get assigned a unique identifier (UID), which is used to track all of their movement through the site.
3. A new JukeBox instance gets created for that user and it is stored in the JukeBoxCollection based on that unique UID.
4. When the user clicks on various links and buttons to move through the site, their UID is sent on to the next page, along with the request to an instance of JukeBoxCollection (which handles all top-level requests for PWS)
5. That JukeBoxCollection instances looks for the UID in the request and if it doesn't find it, creates a new JukeBox for that user and stores it in its hashtable. Otherwise, it finds the user's JukeBox in the hashtable and tells it to process the specific request.

One major problem with this design, however, is that all these JukeBoxes will remain in memory and will not ever get garbage-collected because there is no way to detect the event of the user actually shutting down their browser or moving on to another site.
To solve this, we introduced a timeout value of 20 minutes for each JukeBox. Whenever the user is idle for more than 20 minutes, the system assumes that the user has gone away and removes the JukeBox from JukeBoxCollection, so that the garbage collector would remove it from memory.


Saving and Loading PlayLists

When we first wrote the code to save and load playlists, we had the following goals in mind:
        Goals
In order to validate a playlist when loading it, we inserted a header and a magic number into the file. These took up the first line of the file. If the header and magic number didn't match up correctly, then we could assume that the file was in a format that we couldn't recognize. After the header came a carriage return and the name of the playlist followed by two carriage returns. Then, the diskpath of each song was on each consecutive line.

When P7 rolled around, we noticed the following things

The solution was to embed within the playlist file directions on how a PlayList entry could be added to the playlist. Before I continue, let me describe a bit about our design:

                                            ___________________
| OrderedCollection |
|___________________|
/\
/__\
|
|
_______________ ______|____
| PlayListEntry | | PlayList |
|—————|0.. 1 |———–|
| diskPath |<-------------| name |
| name | |———–|
|—————| | next |
| diskPath: | | name: |
| diskPath | | name |
| name: | | save: |
| name | | load: |
| saveString | |___________|
|_______________|
/\
/__\
|
______|_________
| CachedEntry |
|—————-|
| url |
|—————-|
| diskPath |
| saveString |
|________________|

A PlayList is nothing more than an OrderedCollection of PlayListEntries. The AudioPlayer knows which song to play by calling next on the PlayList. Each type of PlayList entry knows how to create a string (that can be written to disk) that represents itself. When PlayList load: is called, the PlayList reads in a file that contains these strings and then parses them apart to figure out how to create a PlayListEntry for each one. To explain it, I'll show a playlist file and describe what each part does. Each row in the following table represents a different line in the file:
Line in file Description
JUKEBOX#MAGIC:31337 header and magic number
 blank line
Doug's Mixname of playlist
 
CachedEntryname of class representing a PlayListEntry
name:url:diskPath:class message that will create a new instance
Dave Latchaw - the_winding_trail.mp3remaining lines contain parameters for the instance creation message
http://downloads.mp3.com/A...the_winding_trail.mp3
/home/dpowers/.squeak/webcache/16r79A5.mp3
 Blank Line
CachedEntryname of class representing a PlayListEntry
name:url:class message that will create a new instance
Dave Latchaw - grandmas_farm.mp3remaining lines contain parameters for the instance creation message
http://downloads.mp3.com/A...grandmas_farm.mp3
 Blank Line
PlayListEntryname of class representing a PlayListEntry
name:diskPath:class message that will create a new instance
Dave Matthew's - Crashremaining lines contain parameters for the instance creation message
/home/dpowers/mp3/crash.mp3

Notice that the first and second entries are both CachedEntries but they have different message. The first one (which also contains a diskPath) has already been downloaded to disk. The second one hasn't. If a CachedEntry will be downloaded to disk when its diskPath is requested. The last entry is just a regular PlayList and contains a name and a location where it can be found on disk.



Problems we ran into:

Our first few milestones went pretty smoothly, and we had a pretty solid design, but we did hit a few bumps along the way:

Links to this Page