Linked Lists II - Queue

MP3 Player

This assignment demonstrates a queue implemented as a special case of a linked list and how the queue can be managed from an object oriented design perspective.

Create an MP3Player application that maintains a list of songs. The song information must be encapsulated in a class called Song. The following code should be the contents of your Song.h file (be sure to add comment headers to all code in your project):

const int ENTRY_SZ = 512;

class Song

{

private:

char songPath_[ENTRY_SZ]; // Contains the full path name

char songName_[ENTRY_SZ]; // Song name extracted from the path

public:

// Store the path name of the song list file

static char songListFile_[ENTRY_SZ];

static char currentMP3_[ENTRY_SZ];

// Static method to empty the song list file

static void ClearListFile();

Song();

Song(char* name);

~Song();

void SetSongPath(char* path);

const char* GetSongName();

void AppendToListFile();

void PlaySong();

void StopSong();

};

The application must use a linked list implemented as a queue to hold all the songs in memory. You can use the exact same linked list that you created in a previous assignment! They are given here again for your convenience. Your program must use this code for full credit. Instead of the Node and LinkedList member pointers pointing to Star objects as they did in assignment 3, they will point to Song objects in this assignment. Note that there is a new property of the Node class, prev_, and a new method in the LinkedList class, RemoveThisLink. Note that delete should never be called on a void pointer. The data pointer returned by RemoveThisLink must be cast to a Song pointer outside of the Node and LinkedList classes. Then it must be deleted. Remember the LinkedList and Node classes are not supposed to know anything about the Song class.

struct Node

{

void* data_;

Node* prev_;

Node* next_;

Node()

{

data_ = 0;

prev_ = 0;

next_ = 0;

}

};

class LinkedList

{

private:

Node* first_;

Node* last_;

long listLen_;

public:

LinkedList();

~LinkedList();

void AddLinkToBack(void* ptr);

void* RemoveThisLink(Node* node);

void* RemoveLinkFromFront();

Node* GetFirstNode();

long GetListLength();

};

A memory picture of these three constructs (Song class, LinkedList class, and the Node struct) is shown below. The Node objects are contained in the linked list. The LinkedList class can directly access the first and last entries in the list. The data_ property of the Node class is of type void*, which means it can contain the address of any type of object. You are going to store the address of Song objects in them. As you can see, there is one Node object associated with each Song object. So for each song that your program reads in from a file or gets from the console, it must create a new Song object and a new Node object (just as in assignment 3).

This application must display a console menu that looks like this:

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

When a) is selected, the program must prompt the user to enter a file path for an input song list file. It should open the file and read the data for each song from the file one at a time. Note that each song is on a line by itself and includes the full path, such as:

C:\temp\ACDC - Shook You All Night Long.mp3

For each song, it should dynamically create a Song object (using new), store the song data into the object, and add that object to the linked list (which means it must dynamically create a Node object as well). A song list file is provided and is called songList.txt. It is preset with some random mp3 file paths and is an example only. You must update that file with your own songs. Use the correct path and file names for where your mp3 files are located.

Note that your code must be able to handle any path and filenames, including those with embedded spaces, periods, or other characters. Also, your code should be able to handle random spaces and blank lines in the song list file.

When a) is selected a second time, the program must delete every link in the list before reading the new song catalog file. Remember that the Song and the Node objects must be deleted using the delete keyword. The Node object is deleted in the LinkedList class and the Song object must be deleted in the main file (outside of the LinkedList or Node classes).

Note that if b), c), or d) are selected before a file is loaded, print an error message stating that a file must be loaded first, then print the menu again.

The b) option should prompt the user to enter the full path for a new song. The program must dynamically create a Song object (using new), store the path into the object, and add that object to the linked list. The LinkedList class must create a Node object to store the Song object as a void pointer). The program must append the full path to the same song file.

The c) option should prompt the user to input a song title, without the path, at the console and then check if that song exists in the linked list. If found, that song should be deleted from the linked list and from the file. This is why the prev_ property was added to the Node class. In order to delete a node from the middle of the list, the next_ pointer of the previous node must point to the node after the one being deleted. The prev_ pointer allows the previous node to be accessed. Make sure you don’t have any memory leaks when deleting the node. For every execution of a new statement there must be an execution of a delete statement.

The d) option should prompt the user to input a song title without the path. The program should search for the specified song in the linked list and then print to the screen the string “Currently playing SongName XX”, where SongName is the specified song and XX is the lowest 8 bits of the 2's complement of the sum of the ASCII characters in the song name. If the song is not found the program should print “That song is not in the songlist”.

The first step is to add the ASCII values of all the characters in the stored song full path and name, including spaces. Store the sum value in an unsigned int type variable. Next, compute the two’s complement of the sum.

The two’s complement can be computed by flipping all the bits of the number and then adding one. To flip a bit means to change it to the opposite value. If it is a 1, flipping it makes it a 0 and vice versa. Flipping the bit pattern 0110 yields 1001. Bits can be flipped using the exclusive OR operator. In C/C++, this is represented by the caret symbol, ^. Exclusive ORing the sum by all 1s (0xFFFFFFFF in hex notation) has the effect of flipping all the bits.

sum = sum ^ 0xFFFFFFFF; // or sum ^= 0xFFFFFFFF;

Another way to flip bits is to use the bitwise unary complement operator ‘~’:

sum = ~sum;

Next, add 1 to the sum and then truncate all but the lowest 8 bits of the 4 byte sum variable by ANDing with a mask, like this:

sum++; // Add 1

sum = sum & 0x000000FF;

The e) option should print all song file names stored in the linked list to the console. Each song should be on a line by itself, without the file paths. As a user, I will want to select this choice, copy a song name to the clipboard, then select c) or d) and paste the song name at the prompt.

Some Details:

·  If your program opens and closes a file more than one time, which it probably does, add the following clear statement each time after closing it (otherwise, some compilers, like mine, will not allow the file to be reopened):
inFile.close();
inFile.clear(std::ios_base::goodbit);

·  Your program should consist of exactly the following 5 files: LinkedList.h, LinkedList.cpp, Song.h, Song.cpp, main.cpp.

·  The LinkedList class must not contain any reference to the Song class. The LinkedList.h and LinkedList.cpp files should also not contain #include “Song.h”.

·  When adding links to the list, use the AddLinkToBack() method.

·  When deleting the linked list, the RemoveLinkFromFront()method can be used repeatedly until all the links are deleted. Do not delete void pointers! They myst be cast to the type of object they were created as and then deleted. Otherwise, the OS will have no idea how much memory to deallocate.

·  When deleting one specific song, the RemoveThisLink() method may be used. The pointer to the song to be deleted is passed in as a parameter. The pointer must be determined by looping through the list and finding the node with the specific song title to be deleted. Note that a song name cannot be passed in because the LL class would then have to know about the Song class in order to compare the Song names with the passed in names. Instead, the Node pointers can be compared.

·  The main function should look very similar (or identical) to this:

void main()

{

bool terminate = false;

char selection;

while (!terminate)

{

selection = DisplayMenu();

switch(selection)

{

case 'a':

LoadSongFile();

break;

case 'b':

AddNewSong();

break;

case 'c':

DeleteSong();

break;

case 'd':

PlaySong();

break;

case 'e':

PrintAllSongs();

break;

case 'f':

terminate = true;

break;

default:

cout < "That is not a valid choice!\n";

}

}

}

Usage:

Your program should behave and print just as shown here. Note that users should be able to make entries enclosed inside quotes, as well as with no quotes. Songs and directory paths may contain one or more spaces.

User entries are bolded:

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

a

Enter the full file path: C:\Miscellaneous\PCC\CS162\Hmwk4\songList.txt

Loaded file and read 3 Song objects.

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

e

Johnny Cash - I Walk The Line.mp3

OJays-LoveOfMoney.mp3

Rolling_Stones_-_Under_My_Thumb.mp3

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

b

Enter the full song path and name:

“C:\Miscellaneous\Music\U2 - Mysterious Ways.mp3”

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

e

Johnny Cash - I Walk The Line.mp3

OJays-LoveOfMoney.mp3

Rolling_Stones_-_Under_My_Thumb.mp3

U2 - Mysterious Ways.mp3

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

c

Enter the song name with extension: OJays-LoveOfMoney.mp3

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

e

Johnny Cash - I Walk The Line.mp3

Rolling_Stones_-_Under_My_Thumb.mp3

U2 - Mysterious Ways.mp3

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

d

Enter the song name with extension: Johnny Cash - I Walk The Line.mp3 180

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

d

Enter the song name with extension: assadfas

Could not find that song in list!

Please make a selection:

a) Open a song file

b) Add a song

c) Delete a song

d) Play a song

e) Print all songs

f) Quit

File Organization:

Put the Song class declaration in a header file called Song.h. Put the Song class method definitions in a source file called Song.cpp. Put the Node and LinkedList class definitions in corresponding files LinkedList.h and LinkedList.cpp and the main program into a main file called main.cpp.

Deliverables:

Upload the Song.cpp, Song.h, LinkedList.cpp, LinkedList.h and main.cpp files only. Any other files, including zip files, will not be accepted.