dlnasrv_exampleapp/src/exampleappui.cpp
author Sampo Huttunen <sampo.huttunen@nokia.com>
Wed, 03 Nov 2010 11:45:09 +0200
branchIOP_Improvements
changeset 40 08b5eae9f9ff
child 41 b4d83ea1d6e2
permissions -rw-r--r--
merge from Nokia's internal development branch

/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

#include <qlabel.h>
#include <qboxlayout.h>
#include <qgroupbox.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qlayoutitem.h>
#include <qfiledialog.h>
#include <qaction.h>

#include "exampleappui.h"
#include "exampleappengine.h"
#include "trace.h"

/*!
    \class ExampleAppUi
    \brief Implements the application UI for Dlnasrv example application.
*/

/*!
    ExampleAppUi constructor.
 */
ExampleAppUi::ExampleAppUi():
    mEngine(0),
    mSelectedRenderer(0),
    mSelectedFileLabel(0),
    mPlaybackStatus(0),
    mRenderingDevices(0),
    mPauseButton(0),
    mStopButton(0),
    mRewButton(0),
    mFfButton(0),
    mSelectFileButton(0),
    mSearchDevicesButton(0),
    mSelectedFile("")
{
    FUNC_LOG
}

/*!
    ExampleAppUi destructor.
*/
ExampleAppUi::~ExampleAppUi()
{
    FUNC_LOG

    delete mEngine;
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::construct()
{
    FUNC_LOG

    createEngine();
    createUi();
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::createUi()
{
    FUNC_LOG

    // create main view
    QWidget *view = new QWidget;
    setCentralWidget(view);
    
    // create main view layout
    QVBoxLayout *mainLayout = new QVBoxLayout;
    view->setLayout(mainLayout);
    
    // create accesspoint selection
    QLayout *layout = createApSelectionUi();
    mainLayout->addLayout(layout);
    mainLayout->addSpacing(40);
    
    // create renderer selection
    layout = createRendererSelectionUi();
    mainLayout->addLayout(layout);
    mainLayout->addSpacing(40);
    
    // create file selection
    layout = createFileSelectionUi();
    mainLayout->addLayout(layout);
    mainLayout->addSpacing(40);
    
    // create playback ui
    layout = createPlaybackUi();
    mainLayout->addLayout(layout);
    mainLayout->addSpacing(40);
}

/*!
    description
 
    /a
    /return
 */
QLayout *ExampleAppUi::createApSelectionUi()
{
    FUNC_LOG

    QVBoxLayout *layout = new QVBoxLayout;
    QHBoxLayout *topLayout = new QHBoxLayout;
    QLabel *titleLabel = new QLabel(tr("Access point:"));
    QLabel *statusLabel = new QLabel(tr("Not connected"));    

    // connect signals
    connect(mEngine, SIGNAL(iapUpdated(const QString &)), statusLabel, SLOT(setText(const QString &)));
    
    // add widgets to top layout
    topLayout->addWidget(titleLabel);
    topLayout->addWidget(statusLabel);
    
    // add sub layouts to main layout
    layout->addLayout(topLayout);
    
    // update iap
    QString iapName = mEngine->getIapName();
    if (iapName.length())
    {
        statusLabel->setText(iapName);
    }
    
    return layout;
}

/*!
    description
 
    /a
    /return
 */
QLayout *ExampleAppUi::createRendererSelectionUi()
{
    FUNC_LOG

    QVBoxLayout *layout = new QVBoxLayout;
    QHBoxLayout *topLayout = new QHBoxLayout;
    QVBoxLayout *bottomLayout = new QVBoxLayout;
    QLabel *titleLabel = new QLabel(tr("Rendering device:"));
    QLabel *statusLabel = new QLabel(tr("Not connected"));
    QPushButton *searchButton = new QPushButton(tr("Search for new devices"));
    QComboBox *selectionComboBox = new QComboBox;
    
    // connect signals
    connect(searchButton, SIGNAL(clicked()), mEngine, SLOT(searchRenderingDevices()));
    connect(selectionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectRenderingDevice(int)));
    connect(mEngine, SIGNAL(iapUpdated(int)), this, SLOT(enableRenderingDeviceSelection(int)));
    
    // add widgets to top layout
    topLayout->addWidget(titleLabel);
    topLayout->addWidget(statusLabel);
    
    // add widgets to bottom layout
    bottomLayout->addWidget(searchButton);
    bottomLayout->addWidget(selectionComboBox);
    
    // add sub layouts to main layout
    layout->addLayout(topLayout);
    layout->addLayout(bottomLayout);
    
    // store rendering devices
    mRenderingDevices = selectionComboBox;
    mSelectedRenderer = statusLabel;
    mSearchDevicesButton = searchButton;
    
    // disable search button if iap has not been defined
    if (!mEngine->getIap())
    {
        disableRenderingDeviceSelection();
    }
    
    return layout;
}

/*!
    description
 
    /a
    /return
 */
QLayout *ExampleAppUi::createFileSelectionUi()
{
    FUNC_LOG

    QVBoxLayout *layout = new QVBoxLayout;
    QHBoxLayout *topLayout = new QHBoxLayout;
    QVBoxLayout *bottomLayout = new QVBoxLayout;    
    QLabel *titleLabel = new QLabel(tr("Selected file:"));
    QLabel *statusLabel = new QLabel(tr("None"));
    QPushButton *selectButton = new QPushButton(tr("Select media file"));
    
    // connect signals
    connect(selectButton, SIGNAL(clicked()), this, SLOT(selectFile()));

    // add widgets to top layout
    topLayout->addWidget(titleLabel);
    topLayout->addWidget(statusLabel);
    
    // add widgets to bottom layout
    bottomLayout->addWidget(selectButton);
    
    // add sub layouts to main layout
    layout->addLayout(topLayout);
    layout->addLayout(bottomLayout);
    
    // store status label and select file button
    mSelectedFileLabel = statusLabel;
    mSelectFileButton = selectButton;
    
    // disable select file button by default
    disableFileSelection();

    return layout;
}

/*!
    description
 
    /a
    /return
 */
QLayout *ExampleAppUi::createPlaybackUi()
{
    FUNC_LOG

    QVBoxLayout *layout = new QVBoxLayout;
    QHBoxLayout *topLayout = new QHBoxLayout;
    QHBoxLayout *bottomLayout = new QHBoxLayout;
    QLabel *titleLabel = new QLabel(tr("Playback status:"));
    QLabel *statusLabel = new QLabel(tr("Stopped"));
    QPushButton *rewButton = new QPushButton(tr("Rew"));    
    QPushButton *playButton = new QPushButton(tr("Play"));    
    QPushButton *pauseButton = new QPushButton(tr("Pause"));    
    QPushButton *stopButton = new QPushButton(tr("Stop"));    
    QPushButton *ffButton = new QPushButton(tr("Ff"));    
    
    // connect signals
    connect(rewButton, SIGNAL(clicked()), mEngine, SLOT(rew()));
    connect(playButton, SIGNAL(clicked()), mEngine, SLOT(play()));
    connect(pauseButton, SIGNAL(clicked()), mEngine, SLOT(pause()));
    connect(stopButton, SIGNAL(clicked()), mEngine, SLOT(stop()));
    connect(ffButton, SIGNAL(clicked()), mEngine, SLOT(ff()));

    // add widgets to top layout
    topLayout->addWidget(titleLabel);
    topLayout->addWidget(statusLabel);
    
    // add widgets to bottom layout
    bottomLayout->addWidget(rewButton);
    bottomLayout->addWidget(playButton);
    bottomLayout->addWidget(pauseButton);
    bottomLayout->addWidget(stopButton);
    bottomLayout->addWidget(ffButton);
    
    // add sub layouts to main layout
    layout->addLayout(topLayout);
    layout->addLayout(bottomLayout);
    
    // store status label
    mPlaybackStatus = statusLabel;
    mPlayButton = playButton;
    mPauseButton = pauseButton;
    mStopButton = stopButton;
    mRewButton = rewButton;
    mFfButton = ffButton;
    
    // disable all buttons by default
    disablePlayback();

    return layout;
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::createEngine()
{
    FUNC_LOG

    mEngine = new ExampleAppEngine;
    mEngine->construct();
    
    // connect signals
    connect(mEngine, SIGNAL(stateChanged(int)), this, SLOT(updateState(int)));
    connect(mEngine, SIGNAL(renderingDeviceSearchStarted()), this, SLOT(deviceSearchStarted()));
    connect(mEngine, SIGNAL(renderingDeviceFound(const QString &, const QString &)), this, SLOT(addRenderingDevice(const QString &, const QString &)));
    connect(mEngine, SIGNAL(renderingDeviceDisappeared(const QString &, const QString &)), this, SLOT(removeRenderingDevice(const QString &, const QString &)));
    connect(mEngine, SIGNAL(initComplete(int)), this, SLOT(enablePlayback(int)));
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::updateState(int newState)
{
    FUNC_LOG

    switch (newState)
    {
        case ExampleAppEngine::PlaybackStateBuffering:
        {
            mPlaybackStatus->setText(tr("Buffering"));
            break;
        }
        case ExampleAppEngine::PlaybackStatePlaying:
        {
            mPlaybackStatus->setText(tr("Playing"));
            break;
        }
        case ExampleAppEngine::PlaybackStatePaused:
        {
            mPlaybackStatus->setText(tr("Paused"));
            break;
        }
        case ExampleAppEngine::PlaybackStateStopped:
            // fall through
        default:
        {
            mPlaybackStatus->setText(tr("Stopped"));
            break;
        }
    }
    
    // update playback controls
    enablePlayback();
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::selectFile()
{
    FUNC_LOG
    
    mSelectedFile = QFileDialog::getOpenFileName(this,
        tr("Open file"),
        tr("e:\\"),
        tr("Media Files (*.mp3 *.jpg *.mp4)"));
    if (mSelectedFile.length())
    {
        // convert all '/' to '\' since symbian does not understand '/' 
        // characters in the file path
        mSelectedFile.replace("/", "\\");
        
        // update text to ui
        QFileInfo fileInfo(mSelectedFile);
        // use only 20 characters to fit text on screen 
        // since otherwise qt will panic with bad alloc
        mSelectedFileLabel->setText(fileInfo.fileName().left(20));
       
        // resolve and init file for rendering
        int err = mEngine->initFile(mSelectedFile);
        if (err != 0)
        {
            ERROR_1(err, "Failed to init file %s", mSelectedFile.utf16());
            
            mSelectedFile = "";
            
            mSelectedFileLabel->setText(tr("Could not init"));

            disablePlayback();
        }
    }
    else
    {
        mSelectedFileLabel->setText(tr("Not selected"));

        disablePlayback();
    }
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::deviceSearchStarted()
{
    FUNC_LOG
    
    if (!mRenderingDevices->count())
    {
        mSelectedRenderer->setText(tr("Searching"));
    }
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::addRenderingDevice(const QString &name, const QString &uuid)
{
    FUNC_LOG
    
    mRenderingDevices->addItem(name, QVariant(uuid));
}

/*!
    description
 
    /a
    /return
 */
void ExampleAppUi::removeRenderingDevice(const QString &/*name*/, const QString &uuid)
{
    FUNC_LOG

    int count(mRenderingDevices->count());
    for (int i = 0; i < count; i++)
    {
        QVariant userData(mRenderingDevices->itemData(i));
        if (userData.toString() == uuid)
        {
            mRenderingDevices->removeItem(i);
            break;
        }
    }
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::selectRenderingDevice(int index)
{
    FUNC_LOG
    
    // use only 16 characters to fit on screen otherwise qt will panic with bad alloc
    mSelectedRenderer->setText(mRenderingDevices->itemText(index).left(16));
    
    QVariant userData(mRenderingDevices->itemData(index));
    mEngine->prepareRenderingDevice(userData.toString());
    
    enablePlayback();
    enableFileSelection();
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::enablePlayback(int result)
{
    FUNC_LOG
    
    if (result == 0 &&
        mSelectedFile.length())
    {
        switch (mEngine->getPlaybackState())
        {
            case ExampleAppEngine::PlaybackStateBuffering:
            {
                // disable all controls when buffering
                disablePlayback();
                break;
            }
            case ExampleAppEngine::PlaybackStatePlaying:
            {
                mRewButton->setEnabled(mEngine->isSeekSupported());
                mPlayButton->setDisabled(true);
                mPauseButton->setEnabled(mEngine->isPauseSupported());
                mStopButton->setEnabled(true);
                mRewButton->setEnabled(mEngine->isSeekSupported());
                break;
            }
            case ExampleAppEngine::PlaybackStatePaused:
            {
                mRewButton->setEnabled(mEngine->isSeekSupported());
                mPlayButton->setEnabled(true);
                mPauseButton->setDisabled(true);
                mStopButton->setEnabled(true);
                mRewButton->setEnabled(mEngine->isSeekSupported());
                break;
            }
            case ExampleAppEngine::PlaybackStateStopped:
            {
                mRewButton->setDisabled(true);
                mPlayButton->setEnabled(true);
                mPauseButton->setDisabled(true);
                mStopButton->setDisabled(true);
                mRewButton->setDisabled(true);
                break;
            }
            default:
            {
                // invalid state, disable all buttons
                disablePlayback();
                break;
            }
        }
    }
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::disablePlayback()
{
    FUNC_LOG

    mPlayButton->setDisabled(true);
    mPauseButton->setDisabled(true);
    mStopButton->setDisabled(true);
    mRewButton->setDisabled(true);
    mFfButton->setDisabled(true);
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::enableFileSelection()
{
    FUNC_LOG
    
    mSelectFileButton->setEnabled(true);
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::disableFileSelection()
{
    FUNC_LOG

    mSelectFileButton->setDisabled(true);
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::enableRenderingDeviceSelection(int iap)
{
    FUNC_LOG
    
    if (iap)
    {
        mSearchDevicesButton->setEnabled(true);
        mRenderingDevices->setEnabled(true);
    }
}

/*!
    description
    
    /a
    /return
*/
void ExampleAppUi::disableRenderingDeviceSelection()
{
    FUNC_LOG
    
    mSearchDevicesButton->setDisabled(true);
    mRenderingDevices->setDisabled(true);
}

// End of file