PROJECT: JxMusic


Overview

JxMusic is a desktop music player application developed as a school project for the learning of Software Engineering principles. The project is built upon AddressBook(Level 4). The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.

Summary of contributions

  • Code contributed

  • Major enhancement:

    • Designed and implemented the UI component based on AddressBook(Level 4)

      • What it does: It creates a GUI for the product in which the entry for users to interact with the product consists.

      • Justification: This feature functions importantly since the user-product interaction relies on it. It also provides users with the first impression and perception of this product.

      • Highlights: JavaFX was used to aid the implementation. The collocation of .java and .fxml file provides a good structure for the implementation of UI component.

    • Implemented stop, seek and playlist list commands

      • What it does: stop and seek command enables users to stop or seek the playing of tracks. playlist list command lists all playlists in current library.

      • Justification: stop and seek commands suppelment the playback feature of this product. playlist list command enhances the using of playlist management feature.

      • Highlights: seek command takes in special consideration of edge case handling.

  • Other contributions:

    • Minor Enhancement: implemented corresponding test cases to cover newly-implemented codes

    • Project management:

      • Tools: configured RepoSense and Codacy.

      • Issue Tracker Management: Issues relevant to individual responsibility were assigned and handled.

      • Configured and published project website

    • Evidence of helping others: testing of W10-4’s product: #185

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

The launch of jar file and example commands in QuickStart were later revised by David Choo.
The skeleton of stop and seek command was mainly written by David Choo.

Quick Start

  1. Ensure you have Java version 9 or later installed in your Computer.

  2. Download the latest jxmusic.jar here.

  3. Copy the file to the folder you want to use as the home folder for your JxMusic player.

  4. Open a terminal in the folder, enter the command java -jar jxmusic.jar.

    • The command should generate a library folder next to the jar file containing several sample mp3 files.

    • Otherwise, enter unzip jxmusic.jar "library/*"

    • Alternatively, download the library.zip file and unzip it next to the jar.

    • Ensure that you have the library folder with the sample mp3 files otherwise jxmusic won’t start.

    • Then run java -jar jxmusic.jar

  5. The GUI should appear in a few seconds.

    Ui
  6. Type the command in the command box and press Enter to execute it.
    e.g. typing help and pressing Enter will open the help window.

  7. Some example commands you can try with build-in tracks and playlists:

    • playlist list : lists all playlists

    • playlist newp/playlist1 t/Marbles : creates a new playlist named playlist1 with mp3 file Marbles to the JxMusic Player.

    • playlist playp/playlist1 : plays the playlist1

    • exit : exits the app

  8. Refer to [Features] for details of each command.

  9. To add the new tracks to the library, add the mp3 files to the library folder.

  10. Restart the file so that your new tracks could be scanned and showed in UI.

Command Format

  • Words in UPPER_CASE are the parameters to be supplied by the user e.g. in playlist new p/PLAYLIST, PLAYLIST is a parameter which can be used as playlist new p/playlist1.

  • Items in square brackets are optional e.g stepback [s/SECONDS] can be used as stepback or as stepback s/20.

Stopping a play : stop

Stops the track from playing.
Format: stop

Examples:

  • play t/Some Song
    stop
    play
    "Some song" stops playing and replays from the beginning.

Getting the duration of current playing/paused/stopped track: duration

Displays the duration of current playing/paused/stopped track.
Format: duration

  • play t/Some Song
    duration
    The duration of the "Some Song" is displayed on ResultDisplay pane.

Seeking time point : seek

Steps to the specified time point of the current track.
Format: seek d/TIME

  • TIME is in the format of [[h ]m ]s each of which represents a unit of time that will be summed up to get the time point. Only unsigend integers are allowed as time inputs.

  • Examples of valid TIME:

    • 10 (10 sec)

    • 1 59 (1 min 59 sec)

    • 100 (100 sec = 1 min 40 sec)

    • 1 100 (1 min + 100 sec = 2 min 40 sec)

    • 1 99 99 (1 hr + 99 min + 99 sec = 2 hr 40 min 39 sec)

Examples:

  • play t/Some Song
    seek d/1 10
    The track seeks to the 1 min 10 sec point and starts from there.

  • play t/Some Song
    seek d/100
    The track seeks to the 1 min 40 sec point and starts from there.

  • play t/Some Song
    seek d/200000
    If TIME is longer than the song duration, the seek command fails.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Events-Driven nature of the design

The Sequence Diagram below shows how the components interact for the scenario where the user issues the command playlist del 1.

SDforDeletePlaylist
Figure 1. Component interactions for playlist del 1 command (part 1)
Note how the Model simply raises a LibraryChangedEvent when the library data are changed, instead of asking the Storage to save the updates to the hard disk.

The diagram below shows how the EventsCenter reacts to that event, which eventually results in the updates being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time.

SDforDeletePlaylistEventHandling
Figure 2. Component interactions for playlist del 1 command (part 2)
Note how the event is propagated through the EventsCenter to the Storage and UI without Model having to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct coupling between components.

The sections below give more details of each component.

UI component

UiClassDiagram
Figure 3. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, StatusBarFooter, TrackListPanel etc. All these, including the MainWindow, inherit from the abstract UiPart class.

The UI component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml

The UI component,

  • Executes user commands using the Logic component.

  • Binds itself to some data in the Model so that the UI can auto-update when data in the Model change.

  • Responds to events raised from various parts of the App and updates the UI accordingly.

Pause

PauseCommand is implemented to realize the pausing a playing entity. The playing could be resumed after pause and it will play from the time point at which the playing entity is paused. Ultimately, pause() method in javafx.scene.media.MediaPlayer is being called to achieve the performance.

Stop

StopCommand is implemented to achieve the termination of playing of a playing entity. The playing could not be resumed after stop, but the entity being played is remembered and play command after stop will result in the playing of the entity from the beginning. Ultimately, stop() method in javafx.scene.media.MediaPlayer is being called to achieve the performance.

StopSequenceDiagram
Figure 4. Sequence of the stop command

Seek

Current Implementation

The seek functionality enables user to seek the play of a track to a certain time point. This feature is achieved by the implementation of SeekCommand in logic class. To perform user’s instruction, SeekCommandParser is also being implemented. Ultimately, seek(Duration seekTime) method in javafx.scene.media.MediaPlayer is being called to achieve the performance.

Aspect: How seek behaves when the time point is beyond start/stop(aka. total) time
  • Alternative 1 (current choice): throws exception with error message

SeekMethodActivityDiagram
Figure 5. Activity of seek
  • Pro:

    • User will get notification message if their intention could not be achieved

  • Con:

    • Exception will be thrown and the duration information should be made clear to users.

      • Alternative 2: follows the specification of seek(Duration seekTime) in javafx.scene.media.MediaPlayer
        In the documentation of javafx.scene.media.MediaPlayer.seek(Duration seekTime), it specifies the following execution results:
        If seekTime > stop time, seek to stop time.
        If seekTime < start time, seek to start time.

  • Pro:

    • No extra implementation of the retrieval of duration information needs to be done.

  • Con:

    • User will not get notification message if their intention of seeking to a point out of playing time fails.

Duration

Current Implementation

DurationCommand is implemented to enable users to know the duration of current playing track/paused/stopped track. A message contains the duration of the track will displayed in ResultDisplay of the MainWindow.

Aspect: How user get to know the duration of a track
  • Alternative 1 (current choice): implements a command to retrieve the information of duration

    • Pro:

      • User will have the control of the display of the duration information.

    • Con:

      • Compare with Alternative 2, it is less user friendly since extra effort is needed for users to get the information of duration.

  • Alternative 2: displays the duration of tracks in trackCard

UIwithDuration
Figure 6. Proposed UI design with duration shown

This choice is what we chose at first, but subsequently we find out the some methods could not be tested due to the backwardness of javafx (Travis and AppVeyor throw com.sun.media.jfxmedia.mediaexception: could not create player! exception while local tests pass)

  • Pro:

    • It is more convenient and intuitive since no extra effort need to be made to get to know the duration information.

  • Con:

    • javafx feature might be an obstacle when testing.

Use Cases

(For all use cases below, the System is the JxMusic and the Actor is the user, unless specified otherwise)

Use case: List all playlists

MSS

  1. User requests to list playlists.

  2. System displays names of all playlists in library.

    Use case ends.

Use case: Search for a playlist

MSS

  1. User enters the command search.

  2. System displays "Enter playlist name:".

  3. User enters a sequence of characters.

  4. System displays all playlists that include the sequence of characters, in lexicographical order.

    Use case ends.

Extensions

  • 4a. There is no list that matches the name.

    • 4a1. System displays "not found" message.

      Use case ends.