Question

In: Computer Science

At this level your program must read in (from a file) at least four albums and...

At this level your program must read in (from a file) at least four albums and up to 15 tracks for each album.

The information read from the file should include:

  • Number of Albums

  • Album title

  • Artist

  • Artwork file name (place your artwork in an /images folder under the main folder where you run the program)

  • The number of tracks

  • The title of each track

  • The file location of each track

At this level user interaction must be entirely through a GUI. Your GUI interface should show all the albums using either a text description, artwork or both. Users should be able to click on any Album information (i.e the artwork) and the tracks will be listed. The user should then be able to click on a track to play that track. The currently playing track must be indicated somehow (e.g the track could be highlighted or display a simple text message ‘Now playing ..’). If the user clicks on another track (for the current album or another album) then any currently playing track should be stopped and the most recently selected track start playing.

You must use the Gosu audio API for this component.

Given code:

gui_music_player.rb

require 'rubygems'
require 'gosu'

TOP_COLOR = Gosu::Color.new(0xFF1EB1FA)
BOTTOM_COLOR = Gosu::Color.new(0xFF1D4DB5)

module ZOrder
BACKGROUND, PLAYER, UI = *0..2
end

module Genre
POP, CLASSIC, JAZZ, ROCK = *1..4
end

GENRE_NAMES = ['Null', 'Pop', 'Classic', 'Jazz', 'Rock']

class ArtWork
   attr_accessor :bmp

   def initialize (file)
       @bmp = Gosu::Image.new(file)
   end
end

# Put your record definitions here

class MusicPlayerMain < Gosu::Window

   def initialize
        super 600, 800
        self.caption = "Music Player"

       # Reads in an array of albums from a file and then prints all the albums in the
       # array to the terminal
   end

# Put in your code here to load albums and tracks

# Draws the artwork on the screen for all the albums

def draw_albums albums
    # complete this code
end

# Detects if a 'mouse sensitive' area has been clicked on
# i.e either an album or a track. returns true or false

def area_clicked(leftX, topY, rightX, bottomY)
     # complete this code
end


# Takes a String title and an Integer ypos
# You may want to use the following:
def display_track(title, ypos)
   @track_font.draw(title, TrackLeftX, ypos, ZOrder::PLAYER, 1.0, 1.0, Gosu::Color::BLACK)
end


# Takes a track index and an Album and plays the Track from the Album

def playTrack(track, album)
   # complete the missing code
           @song = Gosu::Song.new(album.tracks[track].location)
           @song.play(false)
    # Uncomment the following and indent correctly:
   #   end
   # end
end

# Draw a coloured background using TOP_COLOR and BOTTOM_COLOR

   def draw_background

   end

# Not used? Everything depends on mouse actions.

   def update
   end

# Draws the album images and the track list for the selected album

   def draw
       # Complete the missing code
       draw_background
   end

    def needs_cursor?; true; end

   # If the button area (rectangle) has been clicked on change the background color
   # also store the mouse_x and mouse_y attributes that we 'inherit' from Gosu
   # you will learn about inheritance in the OOP unit - for now just accept that
   # these are available and filled with the latest x and y locations of the mouse click.

   def button_down(id)
       case id
        when Gosu::MsLeft
           # What should happen here?
        end
   end

end

# Show is a method that loops through update and draw

MusicPlayerMain.new.show if __FILE__ == $0

Solutions

Expert Solution

Working code implemented in Ruby and appropriate comments provided for better understanding:

Here I am attaching code for these 3 files:

  • gui_music_player.rb
  • input_functions.rb
  • spare.rb

Source code for gui_music_player.rb:

require 'rubygems'
require 'gosu'
require './input_functions'

TOP_COLOR = Gosu::Color.new(0xFF1EB1FA)
BOTTOM_COLOR = Gosu::Color.new(0xFF1D4DB5)

module ZOrder
BACKGROUND, PLAYER, UI = *0..2
end

module Genre
POP, CLASSIC, JAZZ, ROCK = *1..4
end

GENRE_NAMES = ['Null', 'Pop', 'Hip-hop', 'Rock', 'Jazz']

class ArtWork
   attr_accessor :bmp
   def initialize (file)
       @bmp = Gosu::Image.new(file)
   end
end

class Track
attr_accessor :tra_key, :name, :location
def initialize (tra_key, name, location)
@tra_key = tra_key
@name = name
@location = location
end
end
  
class Album
attr_accessor :pri_key, :title, :artist,:artwork, :genre, :tracks
def initialize (pri_key, title, artist,artwork, genre, tracks)
@pri_key = pri_key
@title = title
       @artist = artist
       @artwork = artwork
@genre = genre
@tracks = tracks
end
end

class Song
   attr_accessor :song
   def initialize (file)
       @song = Gosu::Song.new(file)
   end
end

class MusicPlayerMain < Gosu::Window

   def initialize
   super 800, 600
           self.caption = "Music Player"
           @locs = [60,60]
           @font = Gosu::Font.new(30)
           @a = 0
           @t = 0
   end

   def load_album()
           def read_track (music_file, i)
               track_key = i
               track_name = music_file.gets
               track_location = music_file.gets.chomp
               track = Track.new(track_key, track_name, track_location)
               return track
           end

           def read_tracks music_file
               count = music_file.gets.to_i
               tracks = Array.new()
               i = 0
               while i < count
                   track = read_track(music_file, i+1)
                   tracks << track
                   i = i + 1
               end
               tracks
           end

           def read_album(music_file, i)
               album_pri_key = i
               album_title = music_file.gets.chomp
               album_artist = music_file.gets
               album_artwork = music_file.gets.chomp
               album_genre = music_file.gets.to_i
               album_tracks = read_tracks(music_file)
               album = Album.new(album_pri_key, album_title, album_artist,album_artwork, album_genre, album_tracks)
               return album
           end

           def read_albums(music_file)
               count = music_file.gets.to_i
               albums = Array.new()
               i = 0
                   while i < count
                       album = read_album(music_file, i+1)
                       albums << album
                      
                       i = i + 1
                   end
               return albums
           end

           music_file = File.new("file.txt", "r")
           albums = read_albums(music_file)
           return albums
       end

  
   def needs_cursor?; true; end

  

   def draw_albums(albums)
           @bmp = Gosu::Image.new(albums[0].artwork)
           @bmp.draw(50, 50 , z = ZOrder::PLAYER)

           @bmp = Gosu::Image.new(albums[1].artwork)
           @bmp.draw(50, 310, z = ZOrder::PLAYER)

           @bmp = Gosu::Image.new(albums[2].artwork)
           @bmp.draw(310, 50 , z = ZOrder::PLAYER)
          
           @bmp = Gosu::Image.new(albums[3].artwork)
           @bmp.draw(310, 310, z = ZOrder::PLAYER)
   end

   def draw_button()
       @bmp = Gosu::Image.new("image/play.png")
       @bmp.draw(50, 500, z = ZOrder::UI)

       @bmp = Gosu::Image.new("image/pause.png")
       @bmp.draw(150, 500, z = ZOrder::UI)

       @bmp = Gosu::Image.new("image/stop.png")
       @bmp.draw(250, 500, z = ZOrder::UI)

       @bmp = Gosu::Image.new("image/next.png")
       @bmp.draw(350, 500, z = ZOrder::UI)
   end

   def draw_background()
       draw_quad(0,0, TOP_COLOR, 0, 600, TOP_COLOR, 800, 0, BOTTOM_COLOR, 800, 600, BOTTOM_COLOR, z = ZOrder::BACKGROUND)
   end

   def draw_text(a)
       albums = load_album()
      
end

   def draw
       albums = load_album()
       i = 0
       x = 500
       y = 0
       draw_albums(albums)
       draw_button()
       draw_background()
       if (!@song)
           while i < albums.length
               @font.draw("#{albums[i].title}", x , y+=100, ZOrder::UI, 1.0, 1.0, Gosu::Color::BLACK)
               i+=1
           end
       else
           while i < albums[@a-1].tracks.length
               @font.draw("#{albums[@a-1].tracks[i].name}", x , y+=50, ZOrder::UI, 1.0, 1.0, Gosu::Color::BLACK)
               if (albums[@a-1].tracks[i].tra_key == @t)
                   @font.draw("*", x-20 , y, ZOrder::UI, 1.0, 1.0, Gosu::Color::BLACK)
               end
               i+=1
           end
       end
   end

   def playTrack(t, a)
       albums = load_album()
       i = 0
       while i < albums.length
           if (albums[i].pri_key == a)
               tracks = albums[i].tracks
               j = 0
                       while j< tracks.length
                               if (tracks[j].tra_key == t)
                                   @song = Gosu::Song.new(tracks[j].location)
                                   @song.play(false)
                               end
                               j+=1
                       end
           end
           i+=1
       end

end

def update()
   if (@song)
       if ([email protected]?)
           @t+=1
       end
   end
end


   def area_clicked(mouse_x, mouse_y)
       if ((mouse_x >50 && mouse_x < 201)&& (mouse_y > 50 && mouse_y < 201 ))# x album
           @a = 1
           @t = 1
           playTrack(@t, @a)
       end
       if ((mouse_x > 50 && mouse_x < 210) && (mouse_y > 310 && mouse_y <470))# starboy album
           @a = 2
           @t = 1
           playTrack(@t, @a)
       end
       if ((mouse_x > 310 && mouse_x < 470) && (mouse_y > 50 && mouse_y <210))# do-wops album
           @a = 3
           @t = 1
           playTrack(@t, @a)
       end
       if ((mouse_x > 310 && mouse_x < 470) && (mouse_y > 310 && mouse_y <470))# back in black album
           @a = 4
           @t = 1
           playTrack(@t, @a)
       end
       if ((mouse_x >250 && mouse_x < 375)&& (mouse_y > 500 && mouse_y < 625 ))#stop
           @song.stop
       end
       if ((mouse_x >50 && mouse_x < 175)&& (mouse_y > 500 && mouse_y < 625 ))#play
           @song.play
       end  
       if ((mouse_x >150 && mouse_x < 275)&& (mouse_y > 500 && mouse_y < 625 ))#pause
           @song.pause
       end  
       if ((mouse_x >350 && mouse_x < 475)&& (mouse_y > 500 && mouse_y < 625 ))#next
           if (@t == nil)
               @t = 1
           end
           @t += 1  
           playTrack(@t, @a)
       end  
end

   def button_down(id)
       case id
           when Gosu::MsLeft
               @locs = [mouse_x, mouse_y]
               area_clicked(mouse_x, mouse_y)
       # What should happen here?
   end
   end
end
MusicPlayerMain.new.show if __FILE__ == $0

Code Screenshots:

Source code for input_functions.rb:

# Display the prompt and return the read string
def read_string prompt
   puts prompt
   value = gets.chomp
end

# Display the prompt and return the read float
def read_float prompt
   value = read_string(prompt)
   value.to_f
end

# Display the prompt and return the read integer
def read_integer prompt
   value = read_string(prompt)
   value.to_i
end

# Read an integer between min and max, prompting with the string provided

def read_integer_in_range(prompt, min, max)
   value = read_integer(prompt)
   while (value < min or value > max)
       puts "Please enter a value between " + min.to_s + " and " + max.to_s + ": "
       value = read_integer(prompt);
   end
   value
end

# Display the prompt and return the read Boolean

def read_boolean prompt
   value = read_string(prompt)
   case value
   when 'y', 'yes', 'Yes', 'YES'
       true
   else
       false
   end
end

Code Screenshots:

Source code for spare.rb:

def read_track (music_file, i)
track_key = i
track_name = music_file.gets
track_location = music_file.gets.chomp
track = Track.new(track_key, track_name, track_location)
return track
end

def read_tracks music_file
count = music_file.gets.to_i
tracks = Array.new()
i = 0
while i < count
track = read_track(music_file, i+1)
tracks << track
i = i + 1
end
tracks
end

def read_album(music_file, i)
album_pri_key = i
album_title = music_file.gets.chomp
album_artist = music_file.gets
album_artwork = music_file.gets
album_genre = music_file.gets.to_i
album_tracks = read_tracks(music_file)
album = Album.new(album_pri_key, album_title, album_artist,album_artwork, album_genre, album_tracks)
return album
end

def read_albums(music_file)
count = music_file.gets.to_i
albums = Array.new()
i = 0
while i < count
album = read_album(music_file, i+1)
albums << album
  
i = i + 1
end
return albums
end

def print_tracks tracks
i = 0
while i < tracks.length
print_track(tracks[i])
i = i + 1
end
end

def print_track track
printf("Track key is %d\n", track.tra_key)
puts('Track title is: ' + track.name)
puts('Track file location is: ' + track.location)
printf("\n")
end

def print_album album
printf("albums key: %s\n", album.pri_key)
printf("album title is %s\n", album.title)
printf("%s's artist is %s", album.title, album.artist)
printf("Genre is %s\n", GENRE_NAMES[album.genre])
print_tracks(album.tracks)
printf("\n")
end

def print_albums albums
if (albums)
i = 0
while i < albums.length
print_album(albums[i])
i = i + 1
end
else
printf("there is no file opened\n\n")
end
end

def print_key(album, ans)
if (album)
i = 0
while i < album.length
printf("%s key is %d\n", album[i].title, album[i].pri_key)
i+=1
end
play_album(album)
else
printf("There is no file opened\n\n")
end
end

def play_album(albums)
search_key = read_integer_in_range("Enter album key you want to Play", 1, albums.length)
i = 0
while i < albums.length
if (albums[i].pri_key == search_key)
print_tracks(albums[i].tracks)
play_tracks(albums[i], albums[i].tracks)
end
i+=1
end
end

def play_tracks(albums, tracks)
search_key = read_integer_in_range("Enter Track to be played", 1, tracks.length)
i = 0
while i< tracks.length
if (tracks[i].tra_key == search_key)
printf("playing %s from album %s by %s",tracks[i].name.chomp ,albums.title, albums.artist )
end
i+=1
end
end

music_file = File.new("file.txt", "r")
albums = read_albums(music_file)
print_albums(albums)
# Reads in an array of albums from a file and then prints all the albums in the
# array to the terminal

printf("1 - Select an Album to play\n")
ans = read_integer_in_range("Please Select an option", 1, 1)

if (ans == 1 )
print_key(albums, ans)
end
##############################################

# Detects if a 'mouse sensitive' area has been clicked on
# i.e either an album or a track. returns true or false

def area_clicked(leftX, topY, rightX, bottomY)
# complete this code
end


# Takes a String title and an Integer ypos
# You may want to use the following:
def display_track(title, ypos)
   @track_font.draw(title, TrackLeftX, ypos, ZOrder::PLAYER, 1.0, 1.0, Gosu::Color::BLACK)
end


# Takes a track index and an Album and plays the Track from the Album

def playTrack(track, album)
   # complete the missing code
           @song = Gosu::Song.new(album.tracks[track].location)
           @song.play(false)
# Uncomment the following and indent correctly:
   #   end
   # end
end


# Not used? Everything depends on mouse actions.

   def update
   end

# Draws the album images and the track list for the selected album

   def draw
       # Complete the missing code
       #draw_albums(albums)
       draw_background
   end

   def button_down(id)
       case id
   when Gosu::MsLeft
       # What should happen here?
   end
   end

# Show is a method that loops through update and draw

Code Screenshots:

file.txt(album.txt):

4
X
Ed Sheeran
image/X.jpg
1
6
Sing
music/sing.mp3
Photograph
music/photograph.mp3
Bloodstream
music/bloodstream.mp3
tenerife sea
music/tenerife_sea.mp3
thinking out loud
music/thinking_out_loud.mp3
i see fire
music/i_see_fire.mp3
Starboy
Weekend
image/starboy.jpg
2
4
starboy
music/starboy.mp3
true Colors
music/true_colours.mp3
six feet under
music/six_feet_under.mp3
ordinary life
music/ordinary_life.mp3
Doo-Wops & hooligans
Bruno Mars
image/Doo-Wops & Hooligans.jpg
1
5
Grenade
music/grenade.mp3
Just the way you are
music/just_the_way_you_are.mp3
the lazy song
music/the_lazy_song.mp3
marry you
music/marry_you.mp3
count on me
music/count_on_me.mp3
Back in Black
AC/DC
image/ACDC.jpg
3
3
Givin the dog a bone
music/givin_the_dog_a_bone.mp3
Back in black
music/back_in_black.mp3
You shook me all night long
music/you_shook_me_all_night_long.mp3

Screenshots of file.txt:

Output Screenshots:

Hope it helps, if you like the answer give it thumbs up. Thank you.


Related Solutions

Write a C++ program that creates a file called Readings.txt. Inside the file, your program must...
Write a C++ program that creates a file called Readings.txt. Inside the file, your program must create a list. The list is composed of integer double pairs. There is one pair per line. The integers are in sequence (0, 1, 2, 3, ...) beginning with zero and ending with some random value between 512 and 1024. The doubles should be random values between 50.000 and 90.000. The doubles only have 3 decimal places. The file should look like this (of...
Modify your program from Learning Journal Unit 7 to read dictionary items from a file and...
Modify your program from Learning Journal Unit 7 to read dictionary items from a file and write the inverted dictionary to a file. You will need to decide on the following: How to format each dictionary item as a text string in the input file. How to covert each input string into a dictionary item. How to format each item of your inverted dictionary as a text string in the output file. Create an input file with your original three-or-more...
Write a program in python to read from a file the names and grades of a...
Write a program in python to read from a file the names and grades of a class of students to calculate the class average, the maximum, and the minimum grades. The program should then write the names and grades on a new file identifying the students who passed and the students who failed. The program should consist of the following functions: a) Develop a getGrades() function that reads data from a file and stores it and returns it as a...
Complete the program to read in values from a text file. The values will be the...
Complete the program to read in values from a text file. The values will be the scores on several assignments by the students in a class. Each row of values represents a specific student's scores. Each column represents the scores of all students on a specific assignment. So a specific value is a specific student's score on a specific assignment. The first two values in the text file will give the number of students (number of rows) and the number...
Complete the program to read in values from a text file. The values will be the...
Complete the program to read in values from a text file. The values will be the scores on several assignments by the students in a class. Each row of values represents a specific student's scores. Each column represents the scores of all students on a specific assignment. So a specific value is a specific student's score on a specific assignment. The first two values in the text file will give the number of students (number of rows) and the number...
Program in Bash: Write a program using bash script that can read a file from the...
Program in Bash: Write a program using bash script that can read a file from the same directory, sort the nonrepeating integers from 0-9 from smallest to largest, and output the results on the same line. Do not use the sort function.
Program in Bash: Write a program using bash script that can read a file from the...
Program in Bash: Write a program using bash script that can read a file from the same directory, sort the nonrepeating integers from 0-9 from smallest to largest, and output the results on the same line. Do not use the sort function.
JAVA Assignment: Project File Processing. Write a program that will read in from input file one...
JAVA Assignment: Project File Processing. Write a program that will read in from input file one line at a time until end of file and output the number of words in the line and the number of occurrences of each letter. Define a word to be any string of letters that is delimited at each end by either whitespace, a period, a comma or the beginning or end of the line. You can assume that the input consists entirely of...
This program will read a bunch of numbers from an external file (numbers.txt) and calculate their...
This program will read a bunch of numbers from an external file (numbers.txt) and calculate their total and average. In addition, the total will be multiplied by an integer that is supplied by the user. ** IMPORTANT: The numbers are included in your starter code as a separate file (numbers.txt). Don't touch that file! All of your code should be placed in code.cpp, as usual. ** Input: After all numbers are read, what number would you like to multiply the...
Please write a java program to write to a text file and to read from a...
Please write a java program to write to a text file and to read from a text file.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT