/****************************************************************************
**
** Copyright (C) 2007-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the documentation of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** In addition, as a special exception, Trolltech gives you certain
** additional rights. These rights are described in the Trolltech GPL
** Exception version 1.0, which can be found at
** http://www.trolltech.com/products/qt/gplexception/ and in the file
** GPL_EXCEPTION.txt in this package.
**
** In addition, as a special exception, Trolltech, as the sole copyright
** holder for Qt Designer, grants users of the Qt/Eclipse Integration
** plug-in the right for the Qt/Eclipse Integration to link to
** functionality provided by Qt Designer and its related libraries.
**
** Trolltech reserves all rights not expressly granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

/*!
    \example phonon/musicplayer
    \title Music Player Example

    The Music Player Example shows how to use Phonon - the multimedia
    framework that comes with Qt - to create a simple music player.
    The player can play music files, and provides simple playback
    control, such as pausing, stopping, and resuming the music.

    \image musicplayer.png

    The player has a button group with the play, pause, and stop
    buttons familiar from most music players. The top-most slider
    controls the position in the media stream, and the bottom slider
    allows adjusting the sound volume. 

    The user can use a file dialog to add music files to a table,
    which displays meta information about the music - such as the
    title, album, and artist. Each row contains information about a
    single music file; to play it, the user selects that row and
    presses the play button. Also, when a row is selected, the files
    in the table are queued for playback.

    Phonon offers playback of sound using an available audio device,
    e.g., a sound card or an USB headset. For the implementation, we
    use two objects: a MediaObject, which controls the playback, and
    an AudioOutput, which can output the audio to a sound device. We
    will explain how they cooperate when we encounter them in the
    code. For a high-level introduction to Phonon, see its \l{Phonon
    Overview}{overview}.

    The API of Phonon is implemented through an intermediate
    technology on each supported platform: DirectSound, DirectShow, and
    GStreamer. The sound formats supported may therefore vary from
    system to system. We do not in this example try to determine which
    formats are supported, but let Phonon report an error if the user
    tries to play an unsupported sound file.

    Our player consists of one class, \c MainWindow, which both
    constructs the GUI and handles the playback. We will now go
    through the parts of its definition and implementation that
    concerns Phonon.

    \section1 MainWindow Class Definition

    When we include the necessary headers in our header file, we
    also, for convenience, include the Phonon namespace.

    \snippet phonon/musicplayer/mainwindow.h 0

    Most of the API in \c MainWindow is private, as is often the case
    for classes that represent self-contained windows. We list Phonon
    objects and slots we connect to their signals; we take a closer
    look at them when we walk through the \c MainWindow
    implementation.

    \snippet phonon/musicplayer/mainwindow.h 2

    We use the \c SeekSlider to move the current playback position in
    the media stream, and the \c VolumeSlider controls the sound
    volume. Both of these widgets come ready made with Phonon.

    \snippet phonon/musicplayer/mainwindow.h 1

    The \c MediaObject informs us of the state of the playback and
    properties of the media it is playing back through a series of
    signals. We connect the signals we need to slots in \c MainWindow.
    The \c tableClicked() slot is connected to the table, so that we
    know when the user requests playback of a new music file, by
    clicking on the table.

    \section1 MainWindow Class Implementation

    The \c MainWindow class handles both the user interface and
    Phonon. We will now take a look at the functions that deal with
    Phonon and their code. The code required for setting up the GUI is
    explained elsewhere.

    We start with the constructor:

    \snippet phonon/musicplayer/mainwindow.cpp 0

    We start by instantiating our media and audio output objects.
    As mentioned, the media object knows how to playback
    multimedia (in our case sound files) while the audio output
    can send it to a sound device. 

    For the playback to work, the media and audio output objects need
    to get in contact with each other, so that the media object can
    send the sound to the audio output. Phonon is a graph based
    framework, i.e., its objects are nodes that can be connected by
    paths. Objects are connected using the \c createPath() function,
    which is part of the Phonon namespace.

    \snippet phonon/musicplayer/mainwindow.cpp 1

    We also connect signals of the media object to slots in our \c
    MainWindow. We will examine them shortly.

    \snippet phonon/musicplayer/mainwindow.cpp 2

    Finally, we call private helper functions to set up the GUI.
    The \c setupUi() function contains code for setting up the seek
    , and volume slider. We move on to \c setupUi():

    \snippet phonon/musicplayer/mainwindow.cpp 3
    \dots
    \snippet phonon/musicplayer/mainwindow.cpp 4

    After creating the widgets, they must be supplied with the
    MediaObject and AudioOutput objects they should control.  
    
    In the \c setupActions(), we connect the actions for the play,
    pause, and stop tool buttons, to slots of the media object.

    \snippet phonon/musicplayer/mainwindow.cpp 5

    We move on to the the slots of \c MainWindow, starting with \c
    addFiles(), which is connected to the table. 

    \snippet phonon/musicplayer/mainwindow.cpp 6

    We create a local media object; meta information in music files
    are resolved by a \c MediaObject. We connect the object to our \c
    stateChanged() slot because the object will signal us with
    Phonon::ErrorState if an error occurs.

    \snippet phonon/musicplayer/mainwindow.cpp 7

    We create \l{MediaSource}s for each file the user has selected and
    set them on the media object. Note that the media object does not
    resolve the information when the source is supplied, but after it
    enters the Phonon::PausedState. We therefore call
    \l{MediaObject::}{pause()}. The media object will also emit
    \l{MediaObject::}{metaDataChanged()} after it has resolved the
    meta data.

    After creating \l{QTableWidgetItem}s with the meta data, we
    insert the items into the table (we have omitted that code here).

    \snippet phonon/musicplayer/mainwindow.cpp 8

    When the items are added to the table, we need to append the new
    media source to the \c sources list, which we use to enqueue the
    sources in the media object and update the table.  Finally, we
    update the media objects' queue. The \c enqueueFrom() function
    does this for us.

    The media object informs us of state changes by sending the \c
    stateChanged() signal. The \c stateChanged() slot is connected
    to this signal.

    \snippet phonon/musicplayer/mainwindow.cpp 9

    The \l{MediaObject::}{errorString()} function gives a
    description of the error that is suitable for users of a Phonon
    application. The two values of the \l{Phonon::}{ErrorState}
    enum helps us determine whether it is possible to try another
    media source.

    \snippet phonon/musicplayer/mainwindow.cpp 10

    We update the GUI when the playback state changes, i.e., when it
    starts, pauses, stops, or resumes.

    The media object will report other state changes, as defined by the
    \l{Phonon::}{State} enum.

    The \c tick() slot is connected to a MediaObject signal which is
    emitted when the playback position changes:

    \snippet phonon/musicplayer/mainwindow.cpp 11

    The \c time is given in milliseconds.

    When the table is clicked on with the mouse, \c tableClick()
    is invoked:

    \snippet phonon/musicplayer/mainwindow.cpp 12

    Since we stop the media object, we first check whether it is
    currently playing. \c row contains the row in the table that was
    clicked upon; the indices of \c sources follows the table, so we
    can simply use \c row to find the new source.

    \snippet phonon/musicplayer/mainwindow.cpp 13

    When the media source changes, we simply need to select the
    corresponding row in the table.

    \snippet phonon/musicplayer/mainwindow.cpp 14

    The \c enqueueFrom() function sets up the media object's queue
    when the user changes the source, by clicking on the table or
    adding new files.

    \section1 The main() function.

    Phonon requires that the application has a name; it is set with
    \l{QCoreApplication::}{setApplicationName()}. This is because
    D-Bus, which is used by Phonon on Linux systems, demands this.

    \snippet phonon/musicplayer/main.cpp 1
*/
