You are on page 1of 69

International Institute of Professional Studies

Devi Ahilya Vishwavidyalaya,


Indore

Project Report
On

“POMP”
(Portable Media Player)
rd
Project Report Submitted for the partial fulfilment of III Year of
1/2
Master of Technology (5 Yrs.)
2007

Guided By: Submitted By:


Mr.Vivek Srivastava Achint Verma

1
RECOMMENDATION
The project work entitled “POMP” submitted by “Achint Verma” is a
satisfactory account of the bona-fide work under my supervision is
1/2
recommended towards the end of his VIth semester of M.Tech (5 yrs)
2007.

Guided By
“Mr. Vivek Srivastava”

2
Certificate

This dissertation entitled “POMP” submitted by


“Achint Verma” is approved for the partial
fulfilment account of VIth semester of Master of
1/2
Technology(5 years.

Internal Examiner External Examiner

HOD

3
CONTENTS

PRELIMINARIES

• Recommendation
• Certificate
• Acknowledgement

1. Abstract 5
2. Introduction 6
3. Present Scenario 7
4. Methodology 8
5. Problem Definition 9
6. Feasibility Study 9
7. Business Model 10
8. Requirement analysis 13
9. Initial Study 15
i. Time Based Data 15
ii. Media presentation 15
iii. JMF Architecture 18
iv. Presentation 19
v. Time Model 22
vi. Data Model 23
vii. Controls 24
viii. Event Model 25

10. Functional Modelling 27


i. Context Diagram 27
ii. DFD Level 1 (Basic Player) 28
iii. DFD Level 1 (Mobile application) 29
iv. DFD Level 2 (Player) 30
v. DFD Level 2 (Playlist Manager) 31
vi. State Transition Diagram 32
11. ID3 Tag 33
12. Data Dictionary 34

13. Implementation 38
i. Main Interface 38
ii. Playlist Mnager 39
iii. Tag Editor 40
14. Testing 41
15. Installation 42
16. Limitations 44
17. Conclusion 44
18. Source Code 46

4
Abstract

Module 1: To provide a media player interface on Bluetooth enabled mobile


device. In this module there will be a media player to play songs on a desktop and its
instance interface on mobile device from where we can control playback remotely.

Module 2: Streaming with above media player. Streaming of any song will be
done by media player when it gets a request from its counterpart player on mobile device
to do so. With this a person can listen to any song from media player library by streaming
done with Bluetooth protocol .

Aim :

1. To learn interaction between a desktop and a Bluetooth enabled mobile


device.
2. To provide a virtual command prompt on mobile device to perform various
tasks remotely.
3. To provide new user experience for music freaks so that they can take
advantage of their giant music library (that’s on PC) from anywhere within
range of class B Bluetooth (30 feet).
4. To learn about all the technical restrictions that a developer can face while
learning mobile development using JAVA.

5
Introduction
Recently, MP3 become popular in this generation. Most of the software
companies develop so many types of player which support MP3 file (e.g.
Winamp, Window Media Player, Real, RealOne, etc). But there is not all of the
software which are suitable for all different users.

Pomp is basically a facility for music lovers to control playback of mp3 player right from
there Bluetooth enabled phone. Without a phone , it can work as a standalone mp3-player
on system. This mp3 player has inbuilt ID3 tag editor.
To achieve this we have chosen java as the implementing language because java is
platform independent so what will get can be run on any platform.following java’s “Write
once run everywhere” title.

Benefits of the system


1. Fast standalone mp3 player.
2. Save user time controlling playback from their mobile doing anything else.
3. Facility to save play-list files.
4. ID3 tag editor to edit mp3 metadata.
5. Made in java, hence is extensible, platform independent, robust.

Objectives
The main purpose of POMP is to produce an audio (MP3) player that can be
suitable for different level user. The goals of POMP are:

z Provide a platform to play audio (MP3) file


z Provide different interfaces for different level users
z Support playlist (M3U) file
z Provide playlist management

General Requirements
The following general requirements were laid out for our project named POMP:

• The player can play audio (MP3) file

6
• The player can provide some necessary function of playing audio
(MP3) file, such as previous, next, random, repeat etc.
• Users can choose their interface for their level
• Users can add new songs to the playlist or manage their playlist
• All user’s data and playlists could be stored electronically

Introduction of present scenario


Presently users use software like winamp ,windows media player and open source’s vlc
player. Plug-ins for these software are available to control these players. These packs
have two parts . First part is installed on computer that acts as a server. Second part is
installed on our Bluetooth enabled mobile device. This way program on mobile device
communicates with the application on system. Its generally a two way communication.
Player receives control information and transforms it in proper manner to control
playback of songs.

One of these plug-ins for most popular mp3 player, Winamp is available at its website at
http://www.winamp.com/plugins/browse.php?search=yes&filter=C&query=bluetooth

but main drawback of this plug-in is that its platform dependent i.e. available only for
Microsoft windows. They are coded in languages like c++ or visual basic. Hence there is
no scope for these plug-ins what are written for winamp, windows media player or other
players. They can not run on other operating systems like Linux or Mac OS.

Other option is proprietary software like Bluetooth Remote Control download from
http://www.bluetoothshareware.com/bluetooth_remote_control_manual.asp Demo is
available here. This software is very good as it supports many features like iTunes,
Windows media player, PowerPoint, file browser etc.

Good thing with these popular software is, they are rich in features. They have graphic
equalizer. Support for custom skins, custom plug-ins for extensibility.

Today in the rapidly increasing world of internet, culture for internet radio and online
streaming video is increasing and people are making it a habit. Many media player
nowadays support listening to internet radio channels and live video broadcast. One of
the pioneers in streaming technology is real player which offers great performance even
on low bandwidth.

Missing codec were everybody’s headache few years back but nowadays we have many
software bundles that offer large variety of codec altogether like K-Lite pack have about

7
120 codec in it. Similarily after coming vlc media player, which is open source, scenario
completely changed. Everything I discussed above is present in VLC media payer.

Methodology
I followed SDLC (System Development Life Cycle) for project development phases.

Systems Development Life Cycle (SDLC) or sometimes just (SLC) is defined by the
U.S. Department of Justice (DoJ) as a software development process, although it is also a
distinct process independent of software or other Information Technology considerations.
It is used by a systems analyst to develop an information system, including requirements,
validation, training, and user ownership through investigation, analysis, design,
implementation, and maintenance.

1. Terms Of Reference — the management will decide what capabilities and


objectives they wish the new system to incorporate;
2. Feasibility Study — asks whether the managements' concept of their desired new
system is actually an achievable, realistic goal, in-terms of money, time and end
result difference to the original system. Often, it may be decided to simply update
an existing system, rather than to completely replace one;
3. Fact Finding and Recording — how is the current system used? Often
questionnaires are used here, but also just monitoring (watching) the staff to see
how they work is better, as people will often be reluctant to be entirely honest
through embarrassment about the parts of the existing system they have trouble
with and find difficult if merely asked;
4. Analysis — free from any cost or unrealistic constraints, this stage lets minds run
wild as 'wonder systems' can be thought-up, though all must incorporate
everything asked for by the management in the Terms Of Reference section;
5. Design — designers will produce one or more 'models' of what they see a system
eventually looking like, with ideas from the analysis section either used or
discarded. A document will be produced with a description of the system, but
nothing is specific — they might say 'touchscreen' or 'GUI operating system', but
not mention any specific brands;
6. System Specification — having generically decided on which software packages
to use and hardware to incorporate, you now have to be very specific, choosing
exact models, brands and suppliers for each software application and hardware
device;
7. Implementation and Review — set-up and install the new system (including
writing any custom (bespoke) code required), train staff to use it and then monitor
how it operates for initial problems, and then regularly maintain thereafter.

8
During this stage, any old system that was in-use will usually be discarded once
the new one has proved it is reliable and as usable.

Problem Definition
First of all major problems I was facing at the start of analysis was being very unfamiliar
with the new technologies like JMF and Bluetooth.

In summarized form here are the problems involved with this project.

1. Learning a new API, JMF (Java Media Framework).


2. Learning JSR82, JSR135 packages of java mobile technology.
3. Its difficult to make a system which works on two different architectures, as we
area dealing with a computer plus a mobile device, making all modules work
together successfully is difficult task.
4. To analyze and test whether some of the objectives defined in our required system
can be achieved. As they are not done before or their reference is not available.

Feasibility Study
A feasibility study could be used to test a new working system, which could be used
because:

• The current system may no longer suit its purpose,


• Technological advancement may have rendered the current system redundant,
• The business is expanding, allowing it to cope with extra work load,
• Customers are complaining about the speed and quality of work the business
provides,
• Competitors are now winning a big enough market share due to an effective
integration of a computerized system.

Within a feasibility study, six areas must be reviewed, including those of Economics,
Technical, Schedule, Organizational, Cultural, and Legal.

1.Economic feasibility study

This involves questions such as whether the firm can afford to build the system, whether
its benefits should substantially exceed its costs, and whether the project has higher
priority and profits than other projects that might use the same resources. This also
includes whether the project is in the condition to fulfill all the eligibility criteria and the

9
responsibility of both sides in case there are two parties involved in performing any
project.

** This project has no economical value as its being made for open
source contribution and for sol purpose of learning.

2.Technical feasibility study

This involves questions such as whether the technology needed for the system exists, how
difficult it will be to build, and whether the firm has enough experience using that
technology.The assessment is based on an outline design of system requirements in terms
of Input, Output, Fields, Programs, and Procedures.This can be qualified in terms of
volumes of data,trends,frequency of updating,etc..in order to give an introduction to the
technical system.

1**Needed Technologies are known but whether they work together is question of
research. We drop it on learning and analyzing with the help of so many code
snippets and check their functionality.

2**Streaming of audio as well as video data to Bluetooth device from computer


may be restricted or have a jitter due to low bandwidth of Bluetooth.

3.Behavioral changes study

This involves questions such as whether the system has enough support to be
implemented successfully, whether it brings an excessive amount of change, and whether
the organization is changing too rapidly to absorb it.

**All the behaviors are expected to be in favor of our candidate system as its
promising a flexibility in controlling the music they way you liked and too without
worrying about the operating system you use.

**As its and open source project, it can be downloaded by anybody and can be
modified according to their taste and functional need.

Business Model

10
The term business model describes a broad range of informal and formal models that are
used by enterprises to represent various aspects of business, such as operational
processes, organizational structures, and financial forecasts. Although the term can be
traced to the 1950s, it achieved mainstream usage only in the 1990s. Many informal
definitions of the term can be found in popular business literature, such as the following:

A business model is a conceptual tool that contains a big set of elements


“ and their relationships and allows expressing the business logic of a
specific firm. It is a description of the value a company offers to one or
several segments of customers and of the architecture of the firm and its
network of partners for creating, marketing, and delivering this value and
relationship capital, to generate profitable and sustainable revenue streams. ”
— Osterwalder, Pigneur and Tucci (2005)

**The business model of this system can not be defined as its an open source project
and intended for learning only.

Software Context
Nowadays, computers become more and more popular. Incalculable of
people use computer as their working tool or playing partner. The one who
accessing computer is not a must a computer expert. There is a huge number of
novice begin to use computer everyday. However, some software in the market
is too difficult to the novice. Tricky Player is able to provide a suitable interface to
both novice and normal user. So it must have its own competitive power.

Major constraints
Time

Some of the idea can not be confirmed due to the time, for example, we
want to add the lyric display as one of our function but we don’t have so much
time to investigate how to load the lyric from the song. Also, we want to develop
the player to support more file type (e.g. midi, wav, mpeg, rm etc.) but we don’t
have enough time to improve the software.

11
High competition

Many software with the same functions present in the real world. The
competition becomes high due to the presented software. Also, most of the
software have many advanced functions on playing audio files, that why the
competition become higher and higher.

Knowledge

Since we don’t have any knowledge on multimedia, this may be a barrier


for us to handle the player. So we need to read more books about multimedia in
order to build up our knowledge on this aspect. So we don’t have enough time to
make the player more powerful.

12
Requirement Analysis
and software engineering, requirements analysis encompasses those tasks that go into
determining the requirements of a new or altered system, taking account of the possibly
conflicting requirements of the various stakeholders, such as users. Requirements
analysis is critical to the success of a project.

Systematic requirements analysis is also known as requirements engineering. It is


sometimes referred to loosely by names such as requirements gathering, requirements
capture, or requirements specification. The term "requirements analysis" can also be
applied specifically to the analysis proper (as opposed to elicitation or documentation of
the requirements, for instance).

Hardware Requirements

1. A Bluetooth enabled mobile phone with CLDC 1.1 and JSR82 configuration.
2. A typical Bluetooth USB dongle.
3. a computer with minimum following requirements.

Minimum Recommended

Processor 233 MHz 300 MHz or higher

Memory 64 MB RAM 128 MB RAM or higher

Video adapter and monitor Super VGA (800 x 600) Super VGA (800 x 600) or
higher resolution

Hard drive disk free space 1.5 GB 1.5 GB or higher

Devices Keyboard and mouse Keyboard and mouse

Others Sound card, speakers, Sound card, speakers, and


dh d h h d h

13
Software Requirements

Operating System : Platform Independent but recommended that it should be windows


XP or KDE 3 (when using linux).

Java Runtime environment (JRE) : a software bundle from Sun Microsystems that
allows a computer system to run a Java application. Java applications are in widespread
use and necessary to view many Internet pages.

The software bundle consists of the Java Virtual Machine and programming interface
(API). The API provides a set of standard class libraries. The virtual machine and API
have to be consistent with each other and are therefore bundled together as the JRE. This
can be considered a virtual computer in which the virtual machine is the processor and
the API is the user interface.

Development Tools and Packages

1. JCreator (an IDE for programming in java).


2. JDK(Java Development Kit) 4 or better.
3. Sun Java Wireless Toolkit
4. Java Media Framework (JMF) API for developing media applications.
5. JSR82, JSR135 API for Bluetooth Profiles and Developing Multimedia
application for mobile device.
6. Impronto Simulator (a proprietary software for execution of mobile application in
simulator) provided by Rococo Software.

14
Initial Study

Time Based Data


Any data that changes meaningfully with respect to time can be characterized as time-
based media. Audio clips, MIDI sequences, movie clips, and animations are common
forms of time-based media. Such media data can be obtained from a variety of sources,
such as local or network Þles, cameras, microphones, and live broadcasts.This chapter
describes the key characteristics of time-based media and describes the use of time-
based media in terms of a fundamental data processing model:

Media Presentation
Most time-based media is audio or video data that can be presented through output
devices such as speakers and monitors. Such devices are the most common destination
for media data output. Media streams can also be sent to other destinationsÑfor
example, saved to a Þle or transmitted across the network. An output destination for
media data is sometimes referred to as a data sink.

Presentation Controls
While a media stream is being presented, VCR-style presentation controls are often
provided to enable the user to control playback. For example, a control panel for a movie
player might offer buttons for stopping, starting, fast-forwarding, and rewinding the
movie.

Latency
In many cases, particularly when presenting a media stream that resides on the network,
the presentation of the media stream cannot begin immediately. The time it takes before
presentation can begin is referred to as the start latency. Users might experience this as
a delay between the time that they click the start button and the time when playback
actually starts. Multimedia presentations often combine several types of time-based
media into a synchronized presentation. For example, background music might be
played during an image slide-show, or animated text might be synchronized with an
audio or video clip. When the presentation of multiple media streams is synchronized, it
is essential to take into account the start latency of each streamÑotherwise the playback
of the different streams might actually begin at different times.

15
Presentation Quality
The quality of the presentation of a media stream depends on several factors, including:
¥ The compression scheme used
¥ The processing capability of the playback system
¥ The bandwidth available (for media streams acquired over the network) Traditionally,
the higher the quality, the larger the file size and the greater the processing power and
bandwidth required. Bandwidth is usually represented as the number of bits that are
transmitted in a certain period of time and the bit rate. To achieve high-quality video
presentations, the number of frames displayed in each period of time (the frame rate)
should be as high as possible. Usually movies at a frame rate of 30 frames-per-second
are considered indistinguishable from regular TV broadcasts or video tapes.

Media Processing
In most instances, the data in a media stream is manipulated before it is presented to
the user. Generally, a series of processing operations occur before presentation:

1. If the stream is multiplexed, the individual tracks are extracted.


2. If the individual tracks are compressed, they are decoded.
3. If necessary, the tracks are converted to a different format.
4. Effect filters are applied to the decoded tracks (if desired).

The tracks are then delivered to the appropriate output device. If the media stream is to
be stored instead of rendered to an output device, the processing stages might differ
slightly. For example, if you wanted to capture audio and video from a video camera,
process the data, and save it to a file:

1. The audio and video tracks would be captured.


2. Effect filters would be applied to the raw tracks (if desired).
3. The individual tracks would be encoded.
4. The compressed tracks would be multiplexed into a single media stream.
5. The multiplexed media stream would then be saved to a file.
Demultiplexers and Multiplexers
A demultiplexer extracts individual tracks of media data from a multiplexed media
stream. A mutliplexer performs the opposite function, it takes individual tracks of media
data and merges them into a single multiplexed media stream.

Codecs
A codec performs media-data compression and decompression. When a track is
encoded, it is converted to a compressed format suitable for storage or transmission;
when it is decoded it is converted to a non-compressed (raw) format suitable for
presentation. Each codec has certain input formats that it can handle and certain output
formats that it can generate. In some situations, a series of codecs might be used to
convert from one format to another.

Effect Filters
An effect Filter modifies the track data in some way, often to create special effects such
as blur or echo. Effect Filters are classfied as either pre-processing effects or post-
processing effects, depending on whether they are applied before or after the codec
processes the track. Typically, effect Filters are applied to uncompressed (raw) data.

16
Renderers
A renderer is an abstraction of a presentation device. For audio, the presentation device
is typically the computer’s hardware audio card that outputs sound to the speakers. For
video, the presentation device is typically the computer monitor.
Compositing
Certain specialized devices support compositing. Compositing time-based media is the
process of combining multiple tracks of data onto a single presentation medium. For
example, overlaying text on a video presentation is one common form of compositing.
Compositing can be done in either hardware or software. A device that performs
compositing can be abstracted as a renderer that can receive multiple tracks of input
data.

Media Capture
Time-based media can be captured from a live source for processing and playback. For
example, audio can be captured from a microphone or a video capture card can be used
to obtain video from a camera. Capturing can be thought of as the input phase of the
standard media processing model.
A capture device might deliver multiple media streams. For example, a video camera
might deliver both audio and video. These streams might be captured and manipulated
separately or combined into a single, multiplexed stream that contains both an audio
track and a video track.

Capture Devices
To capture time-based media you need specialized hardware-for example, to capture
audio from a live source, you need a microphone and an appropriate audio card.
Similarly, capturing a TV broadcast requires a TV tuner and an appropriate video
capture card. Most systems provide a query mechanism to find out what capture devices
are available. Capture devices can be characterized as either push or pull sources. For
example, a still camera is a pull source-the user controls when to capture
an image. A microphone is a push source-the live source continuously provides a stream
of audio.
The format of a captured media stream depends on the processing performed by the
capture device. Some devices do very little processing and deliver raw, uncompressed
data. Other capture devices might deliver the data in a compressed format.

Capture Controls
Controls are sometimes provided to enable the user to manage the capture process. For
example, a capture control panel might enable the user to specify the data rate and
encoding type for the captured stream and start and stop the capture process.

17
High-Level Architecture of JMF
Devices such as tape decks and VCRs provide a familiar model for recording,
processing, and presenting time-based media. When you play a movie using a VCR, you
provide the media stream to the VCR by inserting a video tape. The VCR reads and
interprets the data on the tape and sends appropriate signals to your television and
speakers.

JMF uses this same basic model. A data source encapsulates the media stream much
like a video tape and a player provides processing and control mechanisms similar to a
VCR. Playing and capturing audio and video with JMF requires the appropriate input and
output devices such as microphones, cameras, speakers, and monitors. Data sources
and players are integral parts of JMF’s high-level API for managing the capture,
representation, and processing of time-based media. JMF also provides a lower-level
API that supports the seamless integration of custom processing components and
extensions. This layering provides Java developers with an easy-to-use API for
incorporating time-based media into Java programs while maintaining the flexibility and
extensibility required to support advanced media applications and future media
technologies.

High Level JMF Architecture

18
Presentation
In JMF, the presentation process is modeled by the Controller interface. Controller defines
the basic state and control mechanism for an object that controls, presents, or captures
time-based media. It defines the phases that a media controller goes through and
provides a mechanism for controlling the transitions between those phases. A number of
the operations that must be performed before media data can be presented can be time
consuming, so JMF allows programmatic control over when they occur. A Controller posts
a variety of controller-specific MediaEvents to provide notification of changes in its status.
To receive events from a Controller such as a Player, you implement the ControllerListener
interface. The JMF API defines two types of Controllers: Players and Processors. A Player or
Processor is constructed for a particular data source and is normally not re-used to
present other media data.

JMF Processor Model

Players

A Player processes an input stream of media data and renders it at a precise time. A
DataSource is used to deliver the input media-stream to the Player. The rendering
destination depends on the type of media being presented.

JMF Player Model

19
A Player does not provide any control over the processing that it performs or how it
renders the media data. Player supports standardized user control and relaxes some of
the operational restrictions imposed by Clock and Controller.

Classes involved in JMF Player

Player States
A Player can be in one of six states. The Clock interface defines the two primary states:
Stopped and Started. To facilitate resource management, Controller breaks the Stopped
state down into five standby states: Unrealized, Realizing, Realized, Prefetching, and
Prefetched.

20
In normal operation, a Player steps through each state until it reaches the Started state:
1. A Player in the Unrealized state has been instantiated, but does not yet know
anything about its media. When a media Player is first created, it is Unrealized.
2. When realize is called, a Player moves from the Unrealized state into the Realizing
state. A Realizing Player is in the process of determining its resource
equirements. During realization, a Player acquires the resources that it only needs
to acquire once. These might include rendering resources other than exclusive-
use resources. (Exclusiveuse resources are limited resources such as particular
hardware devices that can only be used by one Player at a time; such resources
are acquired during Prefetching.) A Realizing Player often downloads assets over
the network.
3. When a Player finishes Realizing, it moves into the Realized state. A Realized
Player knows what resources it needs and information about the type of media it is
to present. Because a Realized Player knows how to render its data, it can
provide visual components and controls. Its connections to other objects in the
system are in place, but it does not own any resources that would prevent
another Player from starting.
4. When prefetch is called, a Player moves from the Realized state into the
Prefetching state. A Prefetching Player is preparing to present its media. During
this phase, the Player preloads its media data, obtains exclusive-use resources,
and does whatever else it needs to do to prepare itself to play. Prefetching
might have to recur if a Player object’s media presentation is repositioned, or if a
change in the Player object’s rate requires that additional buffers be acquired or
alternate processing take place.
5. When a Player finishes Prefetching, it moves into the Prefetched state. A
Prefetched Player is ready to be started.
6. Calling start puts a Player into the Started state. A Started Player object’s time-base
time and media time are mapped and its clock is running, though the Player might
be waiting for a particular time to begin presenting its media data.

A Player posts TransitionEvents as it moves from one state to another. The ControllerListener
interface provides a way for your program to determine what state a Player is in and to
respond appropriately.

21
1.Time Model
JMF keeps time to nanosecond precision. A particular point in time is typically
represented by a Time object, though some classes also support the specification of time
in nanoseconds.
Classes that support the JMF time model implement Clock to keep track of time for a
particular media stream. The Clock interface defines the basic timing and synchronization
operations that are needed to control the presentation of media data.

A Clock uses a TimeBase to keep track of the passage of time while a media stream is
being presented. A TimeBase provides a constantly ticking time source, much like a
crystal oscillator in a watch. The only information that a TimeBase provides is its current
time, which is referred to as the time-base time. The time-base time cannot be stopped
or reset. Time-base time is often based on the system clock.
A Clock object’s media time represents the current position within a
media stream the beginning of the stream is media time zero, the end of
the stream is the maximum media time for the stream. The duration of the
media stream is the elapsed time from start to finish the length of time
that it takes to present the media stream. (Media objects implement the
Duration interface if they can report a media stream’s duration.)

To keep track of the current media time, a Clock uses:

1. The time-base start-time the time that its TimeBase reports when the presentation
begins.

2. The media start-time the position in the media stream where presentation begins.

3. The playback rate how fast the Clock is running in relation to its TimeBase. The rate
is a scale factor that is applied to the TimeBase. For example, a rate of 1.0
represents the normal playback rate for the media stream, while a rate of 2.0
indicates that the presentation will run at twice the normal rate. A negative rate
indicates that the Clock is running in the opposite direction from its TimeBaseÑfor
example, a negative rate might be used to play a media stream backward.

22
When presentation begins, the media time is mapped to the time-base time and the
advancement of the time-base time is used to measure the passage of time.
During presentation, the current media time is calculated using the following formula:

MediaTime = MediaStartTime + Rate(TimeBaseTime - TimeBaseStartTime)

When the presentation stops, the media time stops, but the time-base time continues to
advance. If the presentation is restarted, the media time is remapped to the current time-
base time.

2.Data Model
JMF media players usually use DataSources to manage the transfer of media-content. A
DataSource encapsulates both the location of media and the protocol and software used to
deliver the media. Once obtained, the source cannot be reused to deliver other media.
A DataSource is identified by either a JMF MediaLocator or a URL (universal resource
locator). A MediaLocator is similar to a URL and can be constructed from a URL, but can be
constructed even if the corresponding protocol handler is not installed on the system. (In
Java, a URL can only be constructed if the corresponding protocol handler is installed on
the system.) A DataSource manages a set of SourceStream objects. A standard data source
uses a byte array as the unit of transfer. A buffer data source uses a Buffer object as its
unit of transfer. JMF defines several types of Data- Source objects:

JMF Data Model

23
Push and Pull Data Sources

Media data can be obtained from a variety of sources, such as local or network files and
live broadcasts. JMF data sources can be categorized according to how data transfer is
initiated:

1. Pull Data-Source - the client initiates the data transfer and controls the flow of
data from pull data-sources. Established protocols for this type of data include
Hypertext Transfer Protocol (HTTP) and FILE. JMF defines two types of pull data
sources: PullDataSource and PullBufferDataSource, which uses a Buffer object as its unit
of transfer.

2. Push Data-Source - the server initiates the data transfer and controls the flow of
data from a push data-source. Push data-sources include broadcast media,
multicast media, and video-on-demand (VOD). For broadcast data, one protocol
is the Real-time Transport Protocol (RTP), under development by the Internet
Engineering Task Force (IETF). The Media Base protocol developed by SGI is
one protocol used for VOD. JMF defines two types of push data sources:
PushDataSource and PushBufferDataSource, which uses a Buffer object as its unit of
transfer.

3.Controls
JMF Control provides a mechanism for setting and querying attributes of an object. A
Control often provides access to a corresponding user interface component that enables
user control over an objectÕs attributes. Many JMF objects expose Controls, including
Controller objects, DataSource objects, DataSink objects, and JMF plug-ins.
Any JMF object that wants to provide access to its corresponding Control objects can
implement the Controls interface. Controls deÞnes methods for retrieving associated Control
objects. DataSource and PlugIn use the Controls interface to provide access to their Control
objects.

Standard Controls
JMF defines the standard Control interfaces shown CachingControl enables download
progress to be monitored and displayed. If a Player or Processor can report its download
progress, it implements this interface so that a progress bar can be displayed to the
user.
GainControl enables audio volume adjustments such as setting the level and muting the
output of a Player or Processor. It also supports a listener mechanism for volume changes.

24
Controller Events
The ControllerEvents posted by a Controller such as a Player or Processor fall into three
categories: change notifications, closed events, and transition events:

1. Change notification events such as RateChangeEvent, DurationUpdateEvent, and


FormatChangeEvent indicate that some attribute of the Controller has changed, often
in response to a method call. For example, a Player posts a RateChangeEvent when
its rate is changed by a call to setRate.
2. TransitionEvents allow your program to respond to changes in a Controller object’s
state. A Player posts transition events whenever it moves from one state to
another ControllerClosedEvents are posted by a Controller when it shuts down. When a
Controller posts a ControllerClosedEvent, it is no longer usable.

3. A ControllerErrorEvent is a special case of ControllerClosedEvent. You can listen for


so that your program can respond to Controller malfunctions to
ControllerErrorEvents
minimize the impact on the user.

4.Event Model
JMF uses a structured event reporting mechanism to keep JMF-based programs
informed of the current state of the media system and enable JMFbased programs to
respond to media-driven error conditions, such as out of data and resource unavailable
conditions. Whenever a JMF object needs to report on the current conditions, it posts a
MediaEvent. MediaEvent is subclassed to identify many particular types of events. These
objects follow the established Java Beans patterns for events.
For each type of JMF object that can
post MediaEvents, JMF deÞnes a corresponding listener interface. To receive notiÞcation
when a MediaEvent is posted, you implement the appropriate listener interface and
register your listener class with the object that posts the event by calling its addListener
method. Controller objects (such as Players and Processors) and certain Control objects such
as GainControl post media events.

JMF Event Model

25
Events in JMF

26
Function Modeling

1. Context Diagram (DFD Level 0)

Above is the top level diagram of the proposed system. It has four external entities
FileSystem, Speakers , Playlist ,Control panel and mobile device panel(optional), as mp3
player can work without it also.

Main process takes three types of information from these entities


1. MP3 Files from file-system
2. File(s) information from Playlist
3. Control Information from Control Interface
.
Audio Data from main process to Speakers is the output.

27
DFD Level 1

Here in this diagram are shown three processes


1. Initialize.
2. Play
3. Manage Play-List

Initialize process collects system information and initializes GUI of our MP3 player.
It also loads previous settings.

Play process has all the functionalities required for playback. Like play, Pause, Stop,
Next, Previous, Mute, Change Volume, Seek.

Manage Playlist process gives facility to load a saved playlist, Save a plalist. Build a
playlist by adding files and folders to it. It also provides an additional facility, to edit
ID3 header information of MP3 file and save them.

28
DFD Level 1

29
DFD Level 2 (Play Process)
Play process has all the functionalities required for playback

Play, Pause, Stop, Next, Previous, Mute, Change Volume, Seek. Only two entities are
there in this level. Setting and temporary store which holds number of current track,
Saves playlist when user quits program.
Rest all controls are basic for any player.

30
DFD Level 2 (Manage Play-List)

This process performs three tasks


1. Open Play-list
2. Save Play-list
3. Edit ID3 tags of a file

Open playlist process opens previously saved playlist files of standard type, .pls.

Save paylist save the currently loaded playlist as .pls file on the file system.

Edit Id3 tag process is used to edit metadata about mp3 files like album, author, title,
duration, year, etc.

31
STD (State Transition Diagram)

State Transition Diagram shows various states of player when user takes different
commands. Here from above diagram programmer can easily interpret the required
objective and easily understand the functionality.
We have three states in player
1. Play
2. Pause
3. Stop
Play state is achieved by taking play action, it can be directed from stop state as well as
paused state.
Pause state is achieved when user takes pause command. Commonly there is
play<>pause state interchange donefrequently.
Stop state activates when user takes stop command or playing song finishes.

32
ID3 Tag

ID3 is a metadata container most often used in conjunction with the MP3 audio file
format. It allows information such as the title, artist, album, track number, or other
information about the file to be stored in the file itself. There are two unrelated versions
of ID3: ID3v1 and ID3v2.

ID3v1 was created by Eric Kemp in 1996 and quickly became the de facto standard for
storing metadata in MP3s. The ID3v1 tag occupies 128 bytes, beginning with the string
TAG. To maintain compatibility with older media players the tag was placed at the end of
the file. Some players played a small burst of static when they read the tag, but most
ignored it, and almost all modern players will correctly skip it.

The placement of the tag, as the data was called, was probably chosen as there were little
chance that it should disturb decoders. In order to make it easy to detect a fixed size of
128 bytes was chosen. The tag has the following layout (as hinted by the scheme to the
right):

Internal layout of an ID3v1 tagged file.

ID3V1 ID3V1.1

33
Data dictionary
Song Information

Name: Track number


Aliases: Song order number
Where/How Read-track-number (input)
Used:
Display-track-number (output)
Description: Track no. = linear number
Format: Numeric Data

Name: Song Title


Aliases: Song name
Where/How Read-song-title (input)
Used:
Display-song-title (output)
Description: Song title = { Letter } n
Letter = [ A | B | C | …. | Z | a | b | c | …. | z | 0 | 1 | …. | 9 ]
Format: Alphanumeric Data

Name: Artist
Aliases:
Where/How Read-artist-name (input)
Used:
Display-artist-name (output)
Description: Artist = { Letter } n
Letter = [ A | B | C | …. | Z | a | b | c | …. | z | 0 | 1 | …. | 9 ]
Format: Alphanumeric Data

34
Name: Album
Aliases: Album name
Where/How Read-album-name (input)
Used:
Display-album-name (output)
Description: Album = { Letter } n
Letter = [ A | B | C | …. | Z | a | b | c | …. | z | 0 | 1 | ….| 9 ]
Format: Alphanumeric Data

Name: Year
Aliases:
Where/How Read-year (input)
Used:
Display-year (output)
Description: Year = { Letter } 4
Letter = [ 0 | 1 | ….| 9 ]
Format: Numeric Data

Name: Genre
Aliases:
Where/How Read-genre (input)
Used:
Display-genre (output)
Description: Genre = [ M | F ]
Format: Character

35
Name: Comment
Aliases:
Where/How Read-comment (input)
Used:
Display-comment (output)
Description: Comment = { Letter } n
Letter = [ A | B | C | …. | Z | a | b | c | …. | z | 0 | 1 | ….| 9 ]
Format: Alphanumeric Data

Name: Copyright
Aliases:
Where/How Read-copyright (input)
Used:
Display-copyright (output)
Description: Copyright = { Letter } n
Letter = [ A | B | C | …. | Z | a | b | c | …. | z | 0 | 1 | ….| 9 ]
Format: Alphanumeric Data

Name: Size
Aliases:
Where/How Read-size-name (input)
Used:
Display-size-name (output)
Description: Size = Number
Format: Numeric Data

36
Name: Length
Aliases: Song length
Where/How Read-length (input)
Used:
Display-length (output)
Description: Length = { 0 | 1 | 2 | …. | 9 } 2 + : + { 0 | 1 | 2 | …. | 9 } 2
Format: Symbol and Numeric Data

37
Implementation (Interfaces)

Implementation is the realization, application, or execution of a plan, idea, model,


design, specification, standard, algorithm, or policy.

In computer science, an implementation is a realization of a technical specification or


algorithm as a program, software component, or other computer system. Many
implementations may exist for a given specification or standard. For example, web
browsers contain implementations of World Wide Web Consortium-recommended
specifications, and software development tools contain implementations of programming
languages.

Our project has 3 forms


1. Main interface (Control panel)
2. Playlist manager
3. ID3 Tag Editor

1.Main interface implements all the basic commands for playback control like play,
pause, stop, previous, next and volume control. Provides facility to open previously
saved playlist, show playlist manager.

Following is a snapshot of main interface.

Following is the list of buttons on this form from left to right.


1. Open PlayList (pls)
2. Show Playlist
3. play
4. pause
5. stop
6. previous
7. next
8. Song info pallatte
9. volume control
10. exit

38
2.Playlist Manager

This interface has a menu, a dynamically expandable table in scrollpane.


Menu bar in this interfae has following commands
File
New (starts a new playlist by clearing old one )
Save (Saves current playlist, opens savefile dialog, in .pls file)
Save as (Saves current playlist, opens savefile dialog, in user define file format)
Exit (Exits from program)
Edit
Add file(s) (Adds files to playlist, openfile dialog opens, multiple files allowed)
Add folder (Adds all files, of the folder and files in folder in side it to playlist)
Edit Tags (Open a tageditor form for selected file)
Remove File (Removes file from playlist)

It has a table which shows list of files that are currently in playlist.
Following metadata about mp3 files are shown in this table
1. Serial Number
2. Track number
3. Track Title
4. Album
5. Artist
6. Time

39
2.ID3 Tag Editor

ID3 tag editor has fields are visible in the above form. Id3 tags are meant for
metadata about the songs. Important point is that is saves entered data in mp3 file
itself so when those files are open with other media players like winamp or windows
media player then id3 tags will be present there.

40
Testing
Software Testing is the process used to help identify the correctness, completeness,
security, and quality of developed computer software. Testing is a process of technical
investigation, performed on behalf of stakeholders, that is intended to reveal quality-
related information about the product with respect to the context in which it is intended to
operate. This includes, but is not limited to, the process of executing a program or
application with the intent of finding errors. Quality is not an absolute; it is value to some
person. With that in mind, testing can never completely establish the correctness of
arbitrary computer software; testing furnishes a 'criticism' or comparison that compares
the state and behaviour of the product against a specification.

There are many approaches to software testing, but effective testing of complex products
is essentially a process of investigation, not merely a matter of creating and following
routine procedure. One definition of testing is "the process of questioning a product in
order to evaluate it", where the "questions" are operations the tester attempts to execute
with the product, and the product answers with its behavior in reaction to the probing of
the tester.Although most of the intellectual processes of testing are nearly identical to that
of review or inspection, the word testing is connoted to mean the dynamic analysis of the
product—putting the product through its paces. Some of the common quality attributes
include capability, reliability, efficiency, portability, maintainability, compatibility, and
usability. A good test is sometimes described as one which reveals an error; however,
more recent thinking suggests that a good test is one which reveals information of interest
to someone who matters within the project community.

For testing our project we followed Black Box technique.

Black box testing takes an external perspective of the test object to derive test cases.
These tests can be functional or non-functional, though usually functional. The test
designer selects valid and invalid input and determines the correct output. There is no
knowledge of the test object's internal structure.

Test Results

** test were performed for various files with different sampling rate, different bit
rate, different file size. And results were satisfying. Quality of sound output was also
acceptable.

*** In testing its found that the project is incomplete with respect to specified
objectives.

41
Installation

Installation (or setup) of a program (including drivers) is the act and the effect of putting
the program in a computer system so that it can be executed.

Most programs are supplied in a condensed form intended for sale and distribution. In
order to be used, they must be 'unpacked' and the relevant information placed correctly on
the computer, taking account of variations between computers, and any customized
settings required by the user. During installation, various tests are made of system
suitability, and the computer is configured to store the relevant files and any necessary
settings required for that program to operate correctly.

One file installation (Setup.exe), an executable file that’s synonymous for installation can
be made for java applications as well. All we need to follow these steps.

Our prerequisites are:

1. Jar file of our project.


2. Jar files of optional API’s we have used in java.
3. JRE should be included in our bundle as it may not be installed on client’s system.
4. All media files, images, databases and sound files should be stored in a well
organized folder which is accessed by our java files by means of absolute path.
Images that are part of user interface can be put in jar file.
5. A full documentation of project, for example as generated by Netbeans.
6. A third party software like Install4j to pack-up all these files together and can be
set accordingly for installation. Means a installable file that creates start menu
shortcuts as well as registers our application to operating system’s registry.

1.Making a JAR file


JAR (Java ARchive) is a ZIP file used to distribute a set of Java classes. It is used to
store compiled Java classes and associated metadata that can constitute a program.

JAR files can be created and extracted using the "jar" command that comes with the JDK.
It can be done using zip tools, but as WinZip has a habit of renaming all-uppercase
directories and files in lower case, this can raise support calls with whoever created the
JAR or the tool authors themselves. WinRAR, on the other hand, retains the original case
of filenames.

A JAR file has a manifest file located in the path META-INF/MANIFEST.MF. The
entries in the manifest file determine how the JAR file will be used. JAR files which are
intended to be executed as standalone programs will have one of their classes specified as
the "main" class. The manifest file would have an entry such as

42
Main-Class: myPrograms.MyClass

Such JAR files are typically started with a command similar to

java -jar foo.jar

These files can also include a Classpath entry, which identifies other JAR files to be
loaded with the JAR. This entry consists of a list of absolute or relative paths to other
JAR files. Although intended to simplify JAR use, in practice, it turns out to be
notoriously brittle as it depends on all the relevant JARs being in the exact locations
specified when the entry-point JAR was built. To change versions or locations of
libraries, a new manifest is needed.

** for making our jar file we first of all keep all 4 class files JavaPlayer.class,
PlaylistManager.class, Settings.java, TagEditor,java in a single directory. Then maing a
folder of images used in our applications within it. Now we will execute following
command

jar cvf pomp.jar *.class images

now we make a text file say mf.txt with following lines in it.

Class-path : jmf.jar helliker.id3.jar mp3plugin.jar

Main-Class : JavaPlayer

Now execute following command.

Jar vfm pomp.jar mf.txt

2. Create Documetation with NetBeans

Create javadoc with Netbeans IDE. For this just right click on project in project window
a>>right click on it and click on generate documentation. Our documentation will be
ready on the fly.

3.Create Setup file with Install4j

Create a installer with the third party software called Install4j. For this just follow the
wizard and make settings accordingly.

43
Limitations of our system
Following are limitations of the system that should be removed.

• Its does not support other file formats than MP3.A file filter is used to accept only
files of mp3 extension.
• It doesn’t support video files.
• While accessing playlist its not possible to command the main interface.
• There is no facility to add or remove columns, i.e. custom column selection for
metadata that are visible in playlist table.
• No support for custom Skins like winamp or windows media player
• No support for Lyrics,
>> there are plug-ins available for other popular software which show lyrics
accordingly with playing speed of song.
• Plug-in support is not there
>> Additional plug-in for controlling output, listening internet radio, network file
listening is not supported
• No graphic equalizer, for filtering sound
• No Visualizer
• Drag and drop facility is not there
• Context menu for explorer is absent. With this facility, user can enqueue
• Lack of intelligence for automatic rating, and grouping of songs, for example,
most recently played, top 25.

Conclusions

Working on this project was quite difficult as even till date project is incomplete. I really
enjoyed this work because of the following reasons

• There is no book available on JMF, so it was quite difficult to learn as I had to


follow “learn by work” technique, originally been main motto at MIT.
• Got to know about optional API’s of java, it started understanding of java’s main
utility , that is its expandability and being open source in nature.
• As even I kept this project as open source, many others will be using my code and
they can make it better and complete. I will start this project on Sourceforge.net,
biggest online open-source contribution site.
• Learned how media files work and got to now internal file structure of MP3 file.
• I knew at the beginning of this project that its too ambitious for me, and chances
for its success are very low. Taking risk helped me to learn faster.

44
Advantages

1. MP3 player of this system is fast, reliable robust and platform independent in
nature as it developed with java language.
2. ID3 tag editor is unique in nature as very few popular media players facilitate us
for same.
3. Its simple user interface is user friendly and even a 5 year kid can operate it .We
have just concentrated on basic functionality of a player that everybody uses.
4. Its expandable, i.e. features of this player can be expanded as project is open
source.

Disadvantages

1. As project is incomplete and due to poor design, its expansion and maintenance is
difficult.
2. Too small scaled for implementation at enterprise level.

45
Source Code
As this project is open source, we are providing full source code.
It has four java source files
1. JavaPlayer.java
2. PlayListManager.java
3. Settings.java
4. TagEditor.java
Following are the optional packages that needs to be downloaded in order to run these
files.
JMF(Java Media Framework). Download from link below
http://java.sun.com/products/java-media/jmf/2.1.1/download.html

MP3 Plug-in for JMF .Download from link below


http://java.sun.com/products/java-media/jmf/mp3/download.html

Hellikar.ID3 package
http://sourceforge.net/projects/jd3lib/

after downloading these packages, copy .jar files from these downloads in your lib/ext
directory of java directory. Then compile those four files and run main file, that is
javaplayer.java

Hierarchy For All Packages

Class Hierarchy

o java.lang.Object
o java.awt.Component (implements java.awt.image.ImageObserver,
java.awt.MenuContainer, java.io.Serializable)
o java.awt.Container
o java.awt.Window (implements
javax.accessibility.Accessible)

46
o java.awt.Dialog
o javax.swing.JDialog (implements
javax.accessibility.Accessible,
javax.swing.RootPaneContainer,
javax.swing.WindowConstants)
o PlaylistManager (implements
java.awt.event.ActionListener,
java.awt.dnd.DropTargetListener,
java.awt.event.MouseListener)

o TagEditor (implements
java.awt.event.ActionListener)
o javax.swing.JWindow (implements
javax.accessibility.Accessible,
javax.swing.RootPaneContainer)
o JavaPlayer (implements
java.awt.event.ActionListener,
javax.swing.event.ChangeListener,
javax.media.ControllerListener,
java.awt.event.MouseMotionListener,
java.lang.Runnable)
o Settings

47
1. JavaPlayer.java
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.media.*;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.EndOfMediaEvent;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.PrefetchCompleteEvent;
import javax.media.RealizeCompleteEvent;
import javax.media.Time;
import javax.media.control.*;
import javax.media.Controller.*;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JSlider;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JWindow;
import javax.swing.filechooser.FileFilter;
import helliker.id3.ID3v2FormatException;
import helliker.id3.PlaylistException;
import helliker.id3.MP3File;
import helliker.id3.Playlist;

public class JavaPlayer extends JWindow implements


ActionListener,ControllerListener,MouseMotionListener,ChangeListener,
Runnable {
private Playlist playlist;
private Player player = null;
private JPanel mainPanel = null;

48
private JProgressBar progressBar = null;
private String fileTitle = "";
private Thread playThread = null;
private JSlider slider;
public JavaPlayer() {
super();
mainPanel = new JPanel(new FlowLayout(FlowLayout.LEADING,1,1));
mainPanel.setBorder(BorderFactory.createRaisedBevelBorder());
mainPanel.addMouseMotionListener(this);
Settings.loadSettings();
Settings.setMainWindowRect(new Rectangle(580,50));
setBounds(Settings.getMainWindowRect());

buildToolbar();
getContentPane().add(mainPanel);
setVisible(true);
playlist = new Playlist();
File playlistFile = new File(Settings.getPlaylistDirectory(),
Settings.getPlaylistFile());
if(playlistFile.exists() && playlistFile.isFile()) {
progressBar.setString("Loading Playlist...");
try {
playlist.loadFromFile(playlistFile);
} catch(IOException ex) {
errorMessage(ex.getMessage());
} catch(PlaylistException ex) {
errorMessage(ex.getMessage());
}
progressBar.setString("");
}
}
private void buildToolbar() {
JButton button ;
button = new JButton(new
ImageIcon(getClass().getClassLoader().getResource("icons/Playlist16.gif
")));
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Open Playlist");
button.setActionCommand("Open Playlist");
button.addActionListener(this);
mainPanel.add(button);

button = new JButton(new


ImageIcon(getClass().getClassLoader().getResource("icons/Manager16.gif"
)));
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Show Playlist");
button.setActionCommand("Playlist Manager");
button.addActionListener(this);
mainPanel.add(button);

button = new JButton(new


ImageIcon(getClass().getClassLoader().getResource("icons/Play16.gif")))
;
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Play");
button.setActionCommand("Play");

49
button.addActionListener(this);
mainPanel.add(button);

button = new JButton(new


ImageIcon(getClass().getClassLoader().getResource("icons/Pause16.gif"))
);
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Pause");
button.setActionCommand("Pause");
button.addActionListener(this);
mainPanel.add(button);
button = new JButton(new
ImageIcon(getClass().getClassLoader().getResource("icons/Stop16.gif")))
;
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Stop");
button.setActionCommand("Stop");
button.addActionListener(this);
mainPanel.add(button);
button = new JButton(new
ImageIcon(getClass().getClassLoader().getResource("icons/Previous16.gif
")));
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Previous Song");
button.setActionCommand("Previous");
button.addActionListener(this);
mainPanel.add(button);

button = new JButton(new


ImageIcon(getClass().getClassLoader().getResource("icons/Next16.gif")))
;
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Next Song");
button.setActionCommand("Next");
button.addActionListener(this);
mainPanel.add(button);

mainPanel.add(Box.createHorizontalStrut(2));

progressBar = new JProgressBar();


progressBar.setPreferredSize(new Dimension(270,18));
progressBar.setStringPainted(true);
progressBar.setFont(new Font("Dialog",Font.BOLD,10));
progressBar.setString("");
mainPanel.add(progressBar);

mainPanel.add(Box.createHorizontalStrut(2));

slider = new JSlider();


slider.setMaximum(100);
slider.setPreferredSize(new Dimension(120,20));
slider.setToolTipText(Integer.toString(slider.getValue()));
slider.addChangeListener(this);
mainPanel.add(slider);

50
button = new JButton(new
ImageIcon(getClass().getClassLoader().getResource("icons/Exit16.gif")))
;
button.setPreferredSize(new Dimension(20,20));
button.setToolTipText("Exit Player");
button.setActionCommand("Exit");
button.addActionListener(this);
mainPanel.add(button);

mainPanel.add(Box.createHorizontalStrut(2));
}
public void errorMessage(String s) {
JOptionPane.showMessageDialog(null, s, "Error",
JOptionPane.ERROR_MESSAGE);
}
private void exitAction() {
Settings.setMainWindowRect(getBounds());
Settings.storeSettings();
if(player != null) {
player.removeControllerListener(this);
player.stop();
player.close();
player = null;
}
if(playThread != null) {
playThread = null;
}
System.exit(0);
}
private void managerAction() {
if(playlist != null) {
PlaylistManager manager = new PlaylistManager(this);
manager.setVisible(true);
}
}
private void playlistAction() {
JFileChooser fileChooser = new
JFileChooser(Settings.getPlaylistDirectory());
fileChooser.setMultiSelectionEnabled(false);
fileChooser.addChoosableFileFilter(new PlaylistFilter());
if(fileChooser.showOpenDialog(null) ==
JFileChooser.APPROVE_OPTION) {
progressBar.setString("Loading Playlist...");
playlist = new Playlist();
try {
File playlistFile = fileChooser.getSelectedFile();
playlist.loadFromFile(playlistFile);

Settings.setPlaylistDirectory(playlistFile.getParent());
Settings.setPlaylistFile(playlistFile.getName());
} catch(IOException ex) {
errorMessage(ex.getMessage());
} catch(PlaylistException ex) {
errorMessage(ex.getMessage());
}
progressBar.setString("");
}

51
}
public Playlist getPlaylist() {
return playlist;
}
public void setPlaylist(Playlist p) {
playlist = p;
}
public Player getPlayer() {
return player;
}
public void play() {
MP3File mp3File = null;
int position = Settings.getPlaylistPosition();
try {
mp3File = (MP3File) playlist.get(position);
fileTitle = mp3File.getTitle();
} catch(ID3v2FormatException ex) {
errorMessage(ex.getMessage());
}
if(player == null) {
try {
File file = new File(mp3File.getPath());
MediaLocator mediaLocator = new
MediaLocator(file.toURL());
player = Manager.createPlayer(mediaLocator);
player.addControllerListener(this);
progressBar.setString("Realizing...");
player.realize();
} catch(MalformedURLException ex) {
errorMessage(ex.getMessage());
} catch(NoPlayerException ex) {
errorMessage(ex.getMessage());
} catch(IOException ex) {
errorMessage(ex.getMessage());
}
} else {
player.start();
progressBar.setString("Playing " + fileTitle);
}
}

private void pause() {


if(player != null) {
MP3File mp3File = null;
int position = Settings.getPlaylistPosition();
try {
mp3File = (MP3File) playlist.get(position);
fileTitle = mp3File.getTitle();
progressBar.setString( fileTitle + " Paused");
} catch(ID3v2FormatException ex) {
errorMessage(ex.getMessage());
}
player.stop();
}
}
public void stop() {
if(player != null) {

52
player.removeControllerListener(this);
player.stop();
player.close();
player = null;
}
if(playThread != null) {
playThread = null;
}
progressBar.setValue(0);
progressBar.setString("");
}
private void previous() {
int position = Settings.getPlaylistPosition();
position--;
if(position < 0)
position = 0;
Settings.setPlaylistPosition(position);
if(player != null)
stop();
play();
}
private void next() {
int position = Settings.getPlaylistPosition();
position++;
if(position >= playlist.size()) {
position = 0;
Settings.setPlaylistPosition(position);
stop();
return;
}
Settings.setPlaylistPosition(position);
if(player != null)
stop();
play();
}
public static void main(String args[]) {
new JavaPlayer();
}
public void actionPerformed(ActionEvent ev) {
JButton button = (JButton) ev.getSource();
String command = button.getActionCommand();
if(command.equals("Exit"))
exitAction();
else if(command.equals("Open Playlist"))
playlistAction();
else if(command.equals("Playlist Manager"))
managerAction();
else if(command.equals("Play"))
play();
else if(command.equals("Pause"))
pause();
else if(command.equals("Stop"))
stop();
else if(command.equals("Previous"))
previous();
else if(command.equals("Next"))
next();

53
}
public void stateChanged(ChangeEvent ev)
{
float vol=slider.getValue();
GainControl gc=player.getGainControl();
gc.setLevel(vol/100);
}
public void controllerUpdate(ControllerEvent ev) {
if(ev instanceof RealizeCompleteEvent) {
player.prefetch();
progressBar.setString("Prefetching...");
}
if(ev instanceof PrefetchCompleteEvent) {
Time time = player.getDuration();
progressBar.setMaximum((int) time.getSeconds());
progressBar.setString("Playing " + fileTitle);
playThread = new Thread(this);
playThread.start();
player.getGainControl().setLevel(1);
player.start();
}
if(ev instanceof EndOfMediaEvent) {
player.removeControllerListener(this);
player.stop();
player.close();
player = null;
if(playThread != null) {
playThread = null;
}
progressBar.setValue(0);
next();
}
}
public void mouseDragged(MouseEvent ev) {
Point loc = getLocation();
Point clk = ev.getPoint();
Point pt = new Point(loc.x + clk.x,loc.y + clk.y);
setLocation(pt);
}
public void mouseMoved(MouseEvent ev) {}
public void run() {
while(playThread != null) {
if(player != null) {
Time time = player.getMediaTime();
progressBar.setValue((int) time.getSeconds());
try {
playThread.sleep(500);
} catch(InterruptedException ex) {}
}
}
}
class PlaylistFilter extends FileFilter{
public boolean accept(File file) {
if(file.isDirectory())
return true;
String s = file.getName().toLowerCase();
if (s.endsWith(".m3u"))

54
return true;
return false;
}
public String getDescription() {
return "Playlist Files";
}

}
}

2. PlalistManager.java
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetListener;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import helliker.id3.ID3v2FormatException;
import helliker.id3.MP3File;
import helliker.id3.NoMPEGFramesException;

import helliker.id3.Playlist;

55
public class PlaylistManager extends JDialog implements ActionListener,
DropTargetListener,MouseListener {
private JavaPlayer player;
private Playlist playlist;
private Vector columns;
private DefaultTableModel model;
private JTable table;
private int[] columnWidth = {75,100,300,300,300,75};
public PlaylistManager(JavaPlayer p) {
super();
setTitle("Playlist Manager");
setModal(true);
setBounds(Settings.getManagerRect());
setJMenuBar(buildMenu());
player = p;
playlist = player.getPlaylist();
columns = new Vector();
columns.addElement("Number");
columns.addElement("Track Number");
columns.addElement("Track Title");
columns.addElement("Album");
columns.addElement("Artist");
columns.addElement("Time");
model = new DefaultTableModel(columns,0) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
table = new JTable(model);
for(int i=0;i<columns.size();i++) {
TableColumn column = table.getColumn((String)
columns.elementAt(i));
column.setPreferredWidth(columnWidth[i]);
}
table.getTableHeader().setResizingAllowed(false);
table.setRowSelectionAllowed(true);

table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.addMouseListener(this);
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
for(int i=0;i<playlist.size();i++)
addToTable((MP3File) playlist.get(i),i+1);

table.setDropTarget(new DropTarget(table,this));
table.getTableHeader().setDropTarget(new
DropTarget(table.getTableHeader(),this));
getJMenuBar().setDropTarget(new
DropTarget(getJMenuBar(),this));
setDropTarget(new DropTarget(this,this));
}
private JMenuBar buildMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
JMenuItem menuItem = new JMenuItem("New");
menuItem.addActionListener(this);

56
menu.add(menuItem);
menuItem = new JMenuItem("Save");
menuItem.addActionListener(this);
menu.add(menuItem);
menuItem = new JMenuItem("Save As");
menuItem.addActionListener(this);
menu.add(menuItem);
// JMenu optionMenu = new JMenu("Save Option");
// ButtonGroup group = new ButtonGroup();
// JRadioButtonMenuItem musicMatch = new
JRadioButtonMenuItem("MusicMatch Format");
// group.add(musicMatch);
// musicMatch.setSelected(!Settings.getWinampFormat());
// musicMatch.addActionListener(this);
// optionMenu.add(musicMatch);
// JRadioButtonMenuItem winamp = new
JRadioButtonMenuItem("Winamp Format");
// group.add(winamp);
// winamp.setSelected(Settings.getWinampFormat());
// winamp.addActionListener(this);
// optionMenu.add(winamp);
// menu.add(optionMenu);
menu.addSeparator();
menuItem = new JMenuItem("Exit");
menuItem.addActionListener(this);
menu.add(menuItem);
menuBar.add(menu);
menu = new JMenu("Edit");
menuItem = new JMenuItem("Add Files");
menuItem.addActionListener(this);
menu.add(menuItem);
menuItem = new JMenuItem("Add Directory");
menuItem.addActionListener(this);

menu.add(menuItem);
menu.addSeparator();
menuItem = new JMenuItem("Edit Tags");
menuItem.addActionListener(this);
menu.add(menuItem);
menu.addSeparator();
menuItem = new JMenuItem("Remove File");
menuItem.addActionListener(this);
menu.add(menuItem);
menuBar.add(menu);
return menuBar;
}
private void addToTable(MP3File mp3File, int pos) {
try {
Vector row = new Vector();
row.addElement(new Integer(pos));
row.addElement(mp3File.getTrack());
row.addElement(mp3File.getTitle());
row.addElement(mp3File.getAlbum());
row.addElement(mp3File.getArtist());
row.addElement(mp3File.getPlayingTimeString());
model.addRow(row);

57
}
catch(ID3v2FormatException ex) {
player.errorMessage(ex.getMessage());
}
}
private void scanDirectory(File dir) {
try {
Playlist pl = new Playlist();
pl.loadFromDirectory(dir,true);
for(int i=0;i<pl.size();i++) {
MP3File mp3 = (MP3File)pl.get(i);
playlist.add(mp3);
addToTable(mp3,model.getRowCount()+1);
}
}
catch(IOException ex) {
player.errorMessage(ex.getMessage());
}
}
private void saveAs() {
JFileChooser fileChooser = new
JFileChooser(Settings.getPlaylistDirectory());

fileChooser.addChoosableFileFilter(new PlaylistFilter());
fileChooser.setMultiSelectionEnabled(false);
if(fileChooser.showSaveDialog(null) ==
JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
String path = file.getParent();
Settings.setPlaylistDirectory(path);
String name = file.getName();
if(!name.endsWith(".m3u"))
name = name + ".m3u";
file = new File(path,name);
savePlaylist(file);
Settings.setPlaylistDirectory(file.getParent());
Settings.setPlaylistFile(file.getName());
}
}
private void savePlaylist(File file) {
try {
playlist.writeToFile(file);
}
catch(IOException ex) {
player.errorMessage(ex.getMessage());
}
}
public void actionPerformed(ActionEvent ev) {
JMenuItem menuItem = (JMenuItem) ev.getSource();
String command = menuItem.getActionCommand();
if(command.equals("New")) {
playlist.clear();
model.setRowCount(0);
Settings.setPlaylistDirectory("");
Settings.setPlaylistFile("");
Settings.setPlaylistPosition(0);

58
}
else if(command.equals("Save")) {
File playlistFile = new
File(Settings.getPlaylistDirectory(), Settings.getPlaylistFile());
if(playlistFile.exists() && playlistFile.isFile())
savePlaylist(playlistFile);
else
saveAs();
}
else if(command.equals("Save As")) {
saveAs();

}
else if(command.equals("Winamp Format")) {
Settings.setWinampFormat(true);
}
else if(command.equals("MusicMatch Format")) {
Settings.setWinampFormat(false);
}
else if(command.equals("Exit")) {
Settings.setManagerRect(getBounds());
player.setPlaylist(playlist);
dispose();
}
else if(command.equals("Add Files")) {
JFileChooser fileChooser = new
JFileChooser(Settings.getOpenDirectory());
fileChooser.addChoosableFileFilter(new MP3Filter());
fileChooser.setMultiSelectionEnabled(true);
if(fileChooser.showOpenDialog(null) ==
JFileChooser.APPROVE_OPTION) {
File[] files = fileChooser.getSelectedFiles();
for(int i=0;i<files.length;i++) {
if(files[i].exists()) {

Settings.setOpenDirectory(files[i].getParent());
try {
MP3File file = new
MP3File(files[i],MP3File.BOTH_TAGS);
playlist.add(file);

addToTable(file,model.getRowCount()+1);
}
catch(ID3v2FormatException ex) {

player.errorMessage(ex.getMessage());
}
catch(IOException ex) {

player.errorMessage(ex.getMessage());
}
catch(NoMPEGFramesException ex) {

player.errorMessage(ex.getMessage());
}
}

59
}

}
}
else if(command.equals("Add Directory")) {
JFileChooser fileChooser = new
JFileChooser(Settings.getOpenDirectory());

fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setMultiSelectionEnabled(true);
if(fileChooser.showOpenDialog(null) ==
JFileChooser.APPROVE_OPTION) {
File[] files = fileChooser.getSelectedFiles();
for(int i=0;i<files.length;i++) {
if(files[i].exists()) {

Settings.setOpenDirectory(files[i].getParent());
scanDirectory(files[i]);
}
}
}
}
else if(command.equals("Edit Tags")) {
ListSelectionModel lsm = table.getSelectionModel();
if (!lsm.isSelectionEmpty()) {
int selectedRow = lsm.getMinSelectionIndex();
MP3File file = (MP3File)
playlist.get(selectedRow);
TagEditor tagEditor = new TagEditor(this,file);
tagEditor.setVisible(true);
playlist.set(selectedRow,file);
try {
Vector row = new Vector();
row.addElement(new
Integer(selectedRow+1));
row.addElement(file.getTrack());
row.addElement(file.getTitle());
row.addElement(file.getAlbum());
row.addElement(file.getArtist());

row.addElement(file.getPlayingTimeString());
model.insertRow(selectedRow,row);
model.removeRow(selectedRow+1);
}
catch(ID3v2FormatException ex) {
player.errorMessage(ex.getMessage());
}
}
}

else if(command.equals("Remove File")) {


int row = table.getSelectedRow();
if(row != -1) {
model.removeRow(row);
playlist.remove(row);
}

60
}
}
public void drop(DropTargetDropEvent ev) {
DropTargetContext targetContext =
ev.getDropTargetContext();
boolean outcome = false;
ev.acceptDrop(DnDConstants.ACTION_COPY);
List dataFlavors = ev.getCurrentDataFlavorsAsList();
Transferable t = ev.getTransferable();
for (int i = 0; i < dataFlavors.size(); i++) {
try {
DataFlavor flavor = (DataFlavor)
dataFlavors.get(i);
if(flavor.isFlavorJavaFileListType()) {
List list = (List)
t.getTransferData(flavor);
for(int j=0;j<list.size();j++) {
File file = (File) list.get(j);
if(file.isDirectory()) {
scanDirectory(file);
}
else
if(file.getName().toLowerCase().endsWith(".mp3")) {
try {
MP3File mp3File = new
MP3File(file);
playlist.add(mp3File);

addToTable(mp3File,playlist.size());
}
catch(ID3v2FormatException
ex) {

player.errorMessage(ex.getMessage());
}
catch(NoMPEGFramesException
ex) {

player.errorMessage(ex.getMessage());
}
}
}
}

outcome = true;
}
catch (IOException ex) {
player.errorMessage(ex.getMessage());
}
catch (UnsupportedFlavorException ex) {
player.errorMessage(ex.getMessage());
}
}
targetContext.dropComplete(outcome);
}
public void dropActionChanged(DropTargetDragEvent ev){}
public void dragOver(DropTargetDragEvent ev){}

61
public void dragEnter(DropTargetDragEvent ev){}
public void dragExit(DropTargetEvent ev) {}
public void mouseClicked(MouseEvent ev) {
if(ev.getClickCount() == 2) {
int row = table.rowAtPoint(ev.getPoint());
if(row != -1) {
Settings.setPlaylistPosition(row);
if(player.getPlayer() != null)
player.stop();
player.play();
}
}
}
public void mousePressed(MouseEvent ev) {}
public void mouseExited(MouseEvent ev) {}
public void mouseEntered(MouseEvent ev) {}
public void mouseReleased(MouseEvent ev) {}
class MP3Filter extends FileFilter implements FilenameFilter{
public boolean accept(File dir, String name) {
String s = name.toLowerCase();
if (s.endsWith(".mp3"))
return true;
File file = new File(dir,name);
if(file.exists() && file.isDirectory())
return true;
return false;
}
public boolean accept(File file) {
if(file.isDirectory())
return true;
String s = file.getName().toLowerCase();

if (s.endsWith(".mp3"))
return true;
return false;
}
public String getDescription() {
return "MP3 Files";
}
}
class PlaylistFilter extends FileFilter{
public boolean accept(File file) {
if(file.isDirectory())
return true;
String s = file.getName().toLowerCase();
if (s.endsWith(".m3u"))
return true;

return false;
}
public String getDescription() {
return "Playlist Files";
}

}
}

62
3.TagEditor.java
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import helliker.id3.ID3v2FormatException;
import helliker.id3.MP3File;
import helliker.id3.NoMPEGFramesException;

public class TagEditor extends JDialog implements ActionListener {


MP3File file;
JTextField
trackNumber,trackTitle,album,artist,comment,composer,copyright,encoded,
original,userDefined,year;
JComboBox genre;
String [] genres = {"Blues","Classic
Rock","Country","Dance","Disco","Funk","General Fiction","Grunge","Hip-
Hop","Jazz","Metal","New
Age","Oldies","Other","Pop","R&B","Rap","Reggae","Rock","Techno",
"Industrial","Alternative","Ska","Death
Metal","Pranks","Soundtrack","Euro-Techno","Ambient","Trip-
Hop","Vocal","Jazz+Funk","Fusion","Trance","Classical","Instrumental","
Acid",
"House","Game","Sound
Clip","Gospel","Noise","AlternRock","Bass","Soul","Punk","Space","Medit
ative","Instrumental Pop","Instrumental
Rock","Ethnic","Gothic","Darkwave",
"Techno-Industrial","Electronic","Pop-
Folk","Eurodance","Dream","Southern
Rock","Comedy","Cult","Gangsta","Top 40","Christian
Rap","Pop/Funk","Jungle","Native American",
"Cabaret","New
Wave","Psychadelic","Rave","Showtunes","Trailer","Lo-Fi","Tribal","Acid
Punk","Acid Jazz","Polka","Retro","Musical","Rock & Roll","Hard
Rock","Folk","Folk-Rock",
"National Folk","Swing","Fast
Fusion","Bebob","Latin","Revival","Celtic","Bluegrass","Avantgarde","Go
thic Rock","Progressive Rock","Psychedelic Rock","Symphonic Rock","Slow
Rock",
"Big Band","Chorus","Easy
Listening","Acoustic","Humour","Speech","Chanson","Opera","Chamber
Music","Sonata","Symphony","Booty Bass","Primus","Porn
Groove","Satire","Slow Jam",

63
"Club","Tango","Samba","Folklore","Ballad","Power
Ballad","Rhythmic Soul","Freestyle","Duet","Punk Rock","Drum Solo","A
capella","Euro-House","Dance Hall"};
public TagEditor(PlaylistManager p, MP3File f) {
super(p,"Tag Editor",true);
getContentPane().setLayout(new GridBagLayout());
file = f;
buildGUI();
populateFields();
pack();
}
private void buildGUI() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(0,1,1,1);
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
getContentPane().add(new JLabel("Track Number:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
trackNumber = new JTextField(3);
getContentPane().add(trackNumber,gbc);
gbc.gridy = 1;
gbc.gridx = 0;
getContentPane().add(new JLabel("Track Title:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
trackTitle = new JTextField(30);
getContentPane().add(trackTitle,gbc);
gbc.gridy = 2;
gbc.gridx = 0;
getContentPane().add(new JLabel("Album:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
album = new JTextField(30);
getContentPane().add(album,gbc);
gbc.gridy = 3;
gbc.gridx = 0;
getContentPane().add(new JLabel("Artist:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
artist = new JTextField(30);
getContentPane().add(artist,gbc);
gbc.gridy = 4;
gbc.gridx = 0;
getContentPane().add(new JLabel("Genre:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
genre = new JComboBox(genres);
getContentPane().add(genre,gbc);
gbc.gridy = 5;
gbc.gridx = 0;
getContentPane().add(new JLabel("Comment:
",SwingConstants.RIGHT),gbc);

64
gbc.gridx = GridBagConstraints.RELATIVE;
comment = new JTextField(30);
getContentPane().add(comment,gbc);
gbc.gridy = 6;
gbc.gridx = 0;
getContentPane().add(new JLabel("Composer:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
composer = new JTextField(30);
getContentPane().add(composer,gbc);
gbc.gridy = 7;
gbc.gridx = 0;
getContentPane().add(new JLabel("Copyright Info:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
copyright = new JTextField(30);
getContentPane().add(copyright,gbc);
gbc.gridy = 8;
gbc.gridx = 0;
getContentPane().add(new JLabel("Encoded By:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
encoded = new JTextField(30);
getContentPane().add(encoded,gbc);
gbc.gridy = 9;
gbc.gridx = 0;
getContentPane().add(new JLabel("Original Artist:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
original = new JTextField(30);
getContentPane().add(original,gbc);
gbc.gridy = 10;
gbc.gridx = 0;
getContentPane().add(new JLabel("URL:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
userDefined = new JTextField(30);
getContentPane().add(userDefined,gbc);
gbc.gridy = 11;
gbc.gridx = 0;
getContentPane().add(new JLabel("Year:
",SwingConstants.RIGHT),gbc);
gbc.gridx = GridBagConstraints.RELATIVE;
year = new JTextField(4);
getContentPane().add(year,gbc);
gbc.gridy = 12;
gbc.gridx = 1;
JPanel buttonPanel = new JPanel();
JButton button = new JButton("OK");
button.addActionListener(this);
buttonPanel.add(button);
button = new JButton("Cancel");
button.addActionListener(this);
buttonPanel.add(button);
getContentPane().add(buttonPanel,gbc);
}
private void populateFields() {

65
try {
trackNumber.setText(file.getTrack());
trackTitle.setText(file.getTitle());
album.setText(file.getAlbum());
artist.setText(file.getArtist());
genre.setSelectedItem(file.getGenre());
comment.setText(file.getComment());
composer.setText(file.getComposer());
copyright.setText(file.getCopyrightInfo());
encoded.setText(file.getEncodedBy());
original.setText(file.getOriginalArtist());
userDefined.setText(file.getUserDefinedURL());
year.setText(file.getYear());
}
catch(ID3v2FormatException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
public void actionPerformed(ActionEvent ev) {
JButton button = (JButton) ev.getSource();
String command = button.getActionCommand();
if(command.equals("OK")) {
try {

file.setTrack(Integer.parseInt(trackNumber.getText()));
file.setTitle(trackTitle.getText());
file.setAlbum(album.getText());
file.setArtist(artist.getText());
file.setGenre((String)genre.getSelectedItem());
file.setComment(comment.getText());
file.setComposer(composer.getText());
file.setCopyrightInfo(copyright.getText());
file.setEncodedBy(encoded.getText());
file.setOriginalArtist(original.getText());

file.setUserDefinedURL(userDefined.getText(),userDefined.getText(
));
file.setYear(year.getText());
file.writeTags();
}
catch(IOException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
dispose();
}

4.Settings.java
import java.awt.Rectangle;
import java.io.File;
import java.io.FileInputStream;

66
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class Settings {


private static Properties properties;

public static String getPlaylistFile() {


return properties.getProperty("player.playlistFile","");
}
public static void setPlaylistFile(String str) {
properties.setProperty("player.playlistFile",str);
}
public static String getPlaylistDirectory() {
return
properties.getProperty("player.playlistDirectory",System.getProperty("u
ser.dir"));
}
public static void setPlaylistDirectory(String str) {
properties.setProperty("player.playlistDirectory",str);
}
public static String getOpenDirectory() {
return
properties.getProperty("player.openDirectory",System.getProperty("user.
dir"));
}
public static void setOpenDirectory(String str) {
properties.setProperty("player.openDirectory",str);
}
public static int getPlaylistPosition() {
return
Integer.parseInt(properties.getProperty("player.playlistPosition","-
1"));
}
public static void setPlaylistPosition(int pos) {

properties.setProperty("player.playlistPosition",Integer.toString
(pos));
}
public static boolean getWinampFormat() {
String tmp =
properties.getProperty("player.winampFormat","false");
Boolean bool = new Boolean(tmp);
return bool.booleanValue();
}
public static void setWinampFormat(boolean winamp) {
properties.setProperty("player.winampFormat",new
Boolean(winamp).toString());
}
public static Rectangle getMainWindowRect() {
String x =
properties.getProperty("player.mainWindow.x","1");
String y =
properties.getProperty("player.mainWindow.y","1");
String width =
properties.getProperty("player.mainWindow.width","600");

67
String height =
properties.getProperty("player.mainWindow.height","25");
return new
Rectangle(Integer.parseInt(x),Integer.parseInt(y),Integer.parseInt(widt
h),Integer.parseInt(height));
}
public static void setMainWindowRect(Rectangle r) {

properties.setProperty("player.mainWindow.x",Integer.toString(r.x
));

properties.setProperty("player.mainWindow.y",Integer.toString(r.y
));

properties.setProperty("player.mainWindow.width",Integer.toString
(r.width));

properties.setProperty("player.mainWindow.height",Integer.toStrin
g(r.height));
}
public static Rectangle getManagerRect() {
String x = properties.getProperty("player.manager.x","1");
String y = properties.getProperty("player.manager.y","1");
String width =
properties.getProperty("player.manager.width","1000");
String height =
properties.getProperty("player.manager.height","500");
return new
Rectangle(Integer.parseInt(x),Integer.parseInt(y),Integer.parseInt(widt
h),Integer.parseInt(height));
}
public static void setManagerRect(Rectangle r) {

properties.setProperty("player.manager.x",Integer.toString(r.x));

properties.setProperty("player.manager.y",Integer.toString(r.y));

properties.setProperty("player.manager.width",Integer.toString(r.
width));

properties.setProperty("player.manager.height",Integer.toString(r
.height));
}
public static void loadSettings() {
properties = new Properties();
File file = new
File(System.getProperty("user.home"),"JavaPlayer.properties");
if(file.exists()) {
try {
FileInputStream istream = new
FileInputStream(file);
properties.load(istream);
istream.close();
}
catch(IOException ex) {
ex.printStackTrace();
}

68
}
}
public static void storeSettings() {
try {
File file = new
File(System.getProperty("user.home"),"JavaPlayer.properties");
FileOutputStream ostream = new
FileOutputStream(file);
properties.store(ostream,"General Player Settings");
ostream.close();
}
catch(IOException ex) {
ex.printStackTrace();
}
}
}

69