CS35: Data Structures and Algorithms

Lab 2: iSwat Media Library

Due on Wednesday, February 13th at 11:59 PM. This is an individual lab. You are to complete this lab on your own, although you may discuss the lab concepts with your classmates. Remember the Academic Integrity Policy: do not show your code to anyone outside of the course staff and do not look at anyone else’s code for this lab. If you need help, please post on the Piazza forum or contact the instructor or ninjas. If you have any doubts about what is okay and what is not, it’s much safer to ask than to risk violating the Academic Integrity Policy.

When you are done with the lab, be sure to fill out this survey on your experience.

Overview

The goal of this lab is to continue your introduction to basic concepts in the C++ programming language. Concepts you will be familiar with after this lab include:

In this lab, you will create several classes representing different types of media, including text, pictures, and videos. All of these classes will be subclasses of an abstract Media class. This Media class will encapsulate all functionality common to all types of media. Your subclasses will add additional unique data as well as implement inherited methods in a way specific to that media. For example, “opening” a text file should be different from “opening” a picture or video.

In addition, you will create a MediaLibrary class which acts as a container for up to 50 Media objects (think of how iTunes stores all of your eBooks, music, movies, etc.). You will also build capability in the MediaLibrary class for obtaining information about your different media objects and for playing the media itself.

Starting Point

You will access your code through a git repository, which is named lab02-<userID>.git. Please access your lab by cloning the appropriate git repository, e.g.:

$ cd ~/cs35
$ git clone git@github.swarthmore.edu:CS35-s19/lab02-userID.git   
$ cd lab02-userID/

You can also get the ssh git url from CS35 github org.

You have been given the following files in your repository. Those highlighted (in bold) will require modification. Otherwise, the file is complete and should not be modified (but you should understand what has been given to you to properly implement this lab).

Running Your Program

Your code in this assignment is broken in to several different files. To aid in the compilation process, we’ve created a Makefile which should make compilation easy. To compile and run your test program, just type:

$ make testMediaLib
$ ./testMediaLib

To compile and run your main program:

$ make iSwatMedia
$ ./iSwatMedia test_data/example1.library # or whichever library file you choose

To compile both, you can run make all or just make.

Implementation Details

There are three main components to this lab that you will need to understand and implement (in part or whole):

The Media Class

The Media class contains virtual methods which are common to all media objects. You will not directly create objects of type Media (in fact, you can’t because it is an abstract class). We have provided this parent class to you; you will need to implement the subclasses to be able to create each of three types of media objects.

See the method comments on the declarations of those classes for more information about the behavior you need to implement. Each subclass will have methods getName(), getDescription(), and open(); the specifics of their implementation depend on the subclass you are implementing. Similarly, the data members needed for each subclass may vary. We have provided the data members for Text, so that would be a good starting point (you will need to determine what data members are needed for the other two subclasses).

The getDescription() method is used to summarize a file for printing in the main application menu (see the application section for an example). Each Media subclass implements it in a different way:

The open method of each Media object should behave as follows:

The MediaLibrary Class

This class keeps track of all Media objects in a library. It allows a user to ask for a description of all Media objects that are in the library and gives them access those objects on request.

Its constructor takes in a single string which represents the name of the file containing the media library. In the MediaLibrary constructor, you should open this file and create Media objects accordingly (and store the number of elements you add using the size data member). You will store each of these in the library data member e.g., library[index] = new Image(...) to add an Image into the library. While the specific subclasses will vary from item to item, C++ will treat them all as of type Media. This is a use of polymorphism; read the section below to ensure you understand how this works.

The Media Library File

When the program starts, the user will provide the name of a media library file which will contains the individual media objects you will load into your library.

The first line of the media library file should indicate the number of media objects it contains so you know exactly how many items to load. Each item is represented by several lines: the first line will describe the media type (i.e., text, image, or video); the remaining lines depend on the specific media type. Here is example1.library followed by a detailed explanation of each line:

3
image
/usr/swat/pics/brownflames.gif
Brown-Flames
image
/usr/swat/pics/aliens.jpg
Aliens
text
/usr/local/doc/GettysburgAddress
Gettysburg-Address

To simplify your job of parsing the file, you can assume that each line of the media library file contains a single element with no whitespace (this creates odd document names, but allows for a single file read per line).

Main Program: iSwatMedia

Example run of the small test library with three media items (example1.library):

$ ./iSwatMedia test_data/example1.library

Welcome to the iSwat Media Library!

0. Quit
1. [image] Brown-Flames
2. [image] Aliens
3. [text] Gettysburg-Address

What would you like to open (or 0 to quit)? 3
  Four Score and seven years ago our fathers brought forth on
this continent a new nation, conceived in Liberty, and dedicated
to the proposition that all men are created equal.
...
[truncated for space]
...
government of the people, by the people, and for the people, shall
not perish from the earth.



0. Quit
1. [image] Brown-Flames
2. [image] Aliens
3. [text] Gettysburg-Address

What would you like to open (or 0 to quit)? -1

Illegal choice.  Would would you like to open (or 0 to quit)? 4

Illegal choice.  Would would you like to open (or 0 to quit)? 2

[should open window with picture of alien drawings from a CS21 lab]

0. Quit
1. [image] Brown-Flames
2. [image] Aliens
3. [text] Gettysburg-Address

What would you like to open (or 0 to quit)? 0

Goodbye!

As mentioned above, your main function should expect the user to provide name of a media library file via the command line. Using that file, it should display a menu listing the media files in order and allow the user to pick a media file to open. If the user gives an invalid file name (or none at all), your program should print an error message on screen and end.

Media files should be listed by positive integers. The first media file you show should be selected by the input 1. After opening that media file, the menu should be repeated again. The program should continue until the user types 0, after which the program should terminate. If the user enters an invalid option, your program should print an error message, then print the menu again.

Tips and Requirements

Polymorphism

Understanding polymorphism in C++ is essential to completing this lab. The main takeaway for this lab is that polymorphic behavior allows you to treat different types of objects (i.e., Video, Image, Text) as if they are of one common type (Media). In fact, aside from the construction of an object, you will never need to specify if a particular object is of a particular subclass. As an example, consider the code provided in testMediaLib.cpp:

Media* testText = new Text("Sample","/home/soni/public/cs35/mediaLibrary/sampleText.txt");
cout << testText->getName() << endl;
cout << testText->getDescription() << endl;
testText->open();  //This should output exactly three lines

Notice that the only time we specify that testText is pointing to an object of type Text is in the construction. For the remaining three lines, the type of testText is just Media*. But the beauty of polymorphism is that we don’t need to know the try underlying type; the code would not change since all subclasses of Media are guaranteed to implement the methods getName(), getDescription(), and open().

Consider this function:

void doStuff(Media* media){
  cout << media->getName() << endl;
  cout << media->getDescription() << endl;
  media->open();
}

This will work! You may wonder how the correct version of open() gets called. While you do not need to specify this, the compiler does keep track and will call the correct version automatically. As you implement the main program, you should identify locations where the true underlying class is abstracted from you as the programmer (i.e., you only know that it is a type of Media object).

Implementation Strategy

We recommend implementing your program in 5 parts:

  1. Initial file I/O – be able to read in an example media library from a file. For now, don’t worry about actually using this information; just print the contents of the file to the screen so you know your file I/O is working.
  2. Text class – be able to view a text file. Test that this works in testMediaLib.cpp.
  3. Image and Video classes – be able to open an image or play a video. Test that this works in testMediaLib.cpp.
  4. Media Library – build and test a MediaLibrary class which holds up to 50 media objects and lets the user access the objects.
  5. Finish the main program – once you have your media objects and MediaLibrary set up, complete the program. When completed, your program should ask the user for a media library, present a menu of media objects, and allow the user to select and open the media.

Your program must use good design principles, and you should use defensive programming as you develop your code. Your program will be tested on your understanding on how to define C++ classes and use inheritance. In addition, you should implement small test functions in testMediaLib.cpp in between each phase. Do not use your MediaLibrary to test and debug your Media objects - doing so is a recipe for extra headaches, and a loss of points for failing to write test code.

Defensive programming

As we learned last week, programs should not assume that provided inputs are valid. For this program, at a minimum you should prevent the following errors:

In addition, you are not responsible for these errors (although you are welcome to think about ways to resolve the issue):

The system Function

The library cstdlib contains a function system which can run commands for you. You pass a C-style string to the system function and it will run it in much the same way as the shell we use to e.g. compile our programs. For instance, the following program will open the Google home page in Firefox (use our program mediaLibPlayer.sh which prevents some annoying behaviour by Firefox). After it does that, it will open a picture.

#include <cstdlib>
#include <string>

using namespace std;

int main() {
  string cmd1 = "mediaLibPlayer.sh http://www.google.com";
  string cmd2 = "gpicview /home/soni/public_html/cs35/f13/Labs/images/01/oberon.png";

  system(cmd1.c_str());
  system(cmd2.c_str());

  return 0;
}

In larger applications, we avoid using the system function in favor of more precise ways to launch other programs from within our own code. For this lab, however, the system function suits us quite well.

Extra Challenges

There are many ways of extending this lab. If you’re looking for an extra challenge, consider implementing one of the following:

These additional features are optional – we’ll look at them, but they won’t be for credit. Make sure you complete and push the main lab before starting any extra challenge, and note in your README file that you’ve done extra challenges so the graders know which version of your lab to grade. (There’s a chance your added features will break our grading scripts; we’ll grade the base version of your lab to ensure you don’t get penalized in the off-chance your extra features break our grading scripts)

Summary

To summarize the requirements of this lab:

Survey

When you have completed your lab, be sure to answer the survey questions to report on your experience with this assignment.

Submit

Once you are satisfied with your code, hand it in using git. Remember the add, commit, push development cycle. You can push as many times as you like, but only the most recent submission will be graded. You may want to run git status to confirm all modifications have been pushed.