In: Computer Science
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
Working code implemented in Ruby and appropriate comments provided for better understanding:
Here I am attaching code for these 3 files:
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.