×
Namespaces

Variants
Actions

Streaming Audio with Qt

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata
Code ExampleTested with
Devices(s): X6, 5235,N97,N8
Compatibility
Platform(s): Symbian
Symbian
Article
Keywords: Phonon
Created: symbianyucca (12 Jul 2010)
Last edited: hamishwillee (11 Oct 2012)


Contents

Overview

In this article we will discuss how we can play audio and video in Qt using Phonon APIs. This API can also be used to play audio/ video streaming.

Streaming1.png Streaming2.png


We will create a Live Audio Streaming application. This application consists of three classes

HttpWindow  : Creates a list of Live Streaming Links, and when user clicks on any of those links it calls the play function

MyMusicTest  : This class is responsible for creating the UI of the application and playing the file when its being selected by the user.

MyPlayerView  : In this class we clear the previous listed audio files (if any) and then starts playing the current one.


Project configuration file (.Pro file)

Add the lib and capabilities in the .pro file

...
QT += core \
gui \
xml \
network \
phonon
...
symbian: {
 
TARGET.CAPABILITY = ReadUSerData \
WriteUserData \
NetworkServices \
LocalServices
}


MyMusicTest Class Definition

#ifndef MYMUSICTEST_H
#define MYMUSICTEST_H
#include <QtGui/QMainWindow>
#include <QStackedWidget>
#include <QAction>
#include <QMenuBar>
#include "MyPlayer.h"
#include "HTTP_window.h"
class MyMusicTest : public QMainWindow
{
Q_OBJECT
public:
MyMusicTest(QWidget *parent = 0);
~MyMusicTest();
private slots:
void about();
void playStream(QString);
void showHttpView();
private:
void createMenus(const bool httpView);
private:
QStackedWidget* mStackedWidget;
MyPlayerView* mMyPlayerView;
HttpWindow* mHttpWindow;
QAction* mAboutAction;
QAction* mExitAction;
QAction* mBackAction;
};
#endif // MYMUSICTEST_H

MyMusicTest Class Implementation

#include <QMessageBox>
#include <QDesktopServices>
#include <QFileDialog>
#include <QUrl>
 
 
#include "MyMusicTest.h"
 
MyMusicTest::MyMusicTest(QWidget *parent): QMainWindow(parent)
{
setWindowTitle("My Music Player");
 
mStackedWidget = new QStackedWidget;
setCentralWidget(mStackedWidget);
 
mHttpWindow = new HttpWindow();
mStackedWidget->addWidget(mHttpWindow);
 
mMyPlayerView = new MyPlayerView;
mStackedWidget->addWidget(mMyPlayerView);
 
mStackedWidget->setCurrentIndex(0);
 
mAboutAction = new QAction(tr("About"), this);
mExitAction = new QAction(tr("Exit"), this);
mBackAction = new QAction(tr("Back"), this);
 
connect(mHttpWindow, SIGNAL(streamSelected(QString)), this, SLOT(playStream(QString)));
connect(mMyPlayerView, SIGNAL(backButtonPressed()), this, SLOT(showHttpView()));
 
connect(mExitAction, SIGNAL(triggered()), this, SLOT(close()));
connect(mAboutAction, SIGNAL(triggered()), this, SLOT(about()));
connect(mBackAction, SIGNAL(triggered()), this, SLOT(showHttpView()));
 
createMenus(true);
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

MyMusicTest::~MyMusicTest()
{
 
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyMusicTest::createMenus(const bool httpView)
{
QList<QAction*> actList = menuBar()->actions();
for(int i=0; i < actList.count(); i++){
menuBar()->removeAction(actList.at(i));
}
 
if(httpView){
menuBar()->addAction(mAboutAction);
menuBar()->addAction(mExitAction);
}else{
menuBar()->addAction(mBackAction);
}
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyMusicTest::showHttpView()
{
mMyPlayerView->StopPlay();
mStackedWidget->setCurrentIndex(0);
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyMusicTest::playStream(QString stream)
{
mStackedWidget->setCurrentIndex(1);
createMenus(false);
 
QUrl url(stream);
 
mMyPlayerView->SetUrl(url);
mMyPlayerView->playNow();
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyMusicTest::about()
{
QMessageBox::information(this, tr("About stream example"),
tr("This Music Player example shows how to use Phonon for streaming audio."
"work in progress..."));
}

The createMenus() function creates the menu of the application. showHttpView() stops the playback if its playing and set the current index of the streaming list to zero. playStream() set the selected URL and pass it to SetUrl() function and then call the playNow() function of MyPlayerView class.


MyPlayerView Class Definition

#ifndef MYPLAYER_H_
#define MYPLAYER_H_
#include <QWidget>
#include <phonon/audiooutput.h>
#include <phonon/VideoWidget.h>
#include <phonon/seekslider.h>
#include <phonon/mediaobject.h>
#include <phonon/volumeslider.h>
#include <phonon/backendcapabilities.h>
#include <QList>
#include <QLabel>
#include <QPushButton>
class QAction;
class QTableWidget;
class QLCDNumber;
 
class MyPlayerView : public QWidget
{
Q_OBJECT
public:
MyPlayerView();
QSize sizeHint() const {
return QSize(500, 300);
}
public slots:
void playNow();
void StopPlay();
void SetFile(const QString& file);
void SetUrl(const QUrl &url);
void stateChanged(Phonon::State newState, Phonon::State oldState);
void sourceChanged(const Phonon::MediaSource &source);
void aboutToFinish();
void setBufferingValue(int value);
void tick(qint64 time);
signals:
void backButtonPressed();
private:
void setupUi();
private:
Phonon::MediaObject* mediaObject;
Phonon::AudioOutput* audioOutput;
Phonon::MediaSource source;
Phonon::VideoWidget* videoWidget;
QLabel* mStatusLabel;
QLabel* mStatusTitle;
QAction* playAction;
QAction* pauseAction;
QAction* stopAction;
QLCDNumber* timeLcd;
Phonon::VolumeSlider* volumeSlider;
QWidget* dummy;
};
#endif /* MYPLAYER_H_ */



MyPlayerView Class Implementation

#include <QtGui>
 
#include "MyPlayer.h"
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

MyPlayerView::MyPlayerView()
{
audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
mediaObject = new Phonon::MediaObject(this);
 
mediaObject->setTickInterval(1000);
connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
connect(mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),this, SLOT(stateChanged(Phonon::State,Phonon::State)));
connect(mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),this, SLOT(sourceChanged(Phonon::MediaSource)));
connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
 
connect(mediaObject, SIGNAL(bufferStatus(int)), this, SLOT(setBufferingValue(int)));
 
Phonon::createPath(mediaObject, audioOutput);
 
playAction = new QAction(style()->standardIcon(QStyle::SP_MediaPlay), tr("Play"), this);
playAction->setDisabled(true);
 
pauseAction = new QAction(style()->standardIcon(QStyle::SP_MediaPause), tr("Pause"), this);
pauseAction->setDisabled(true);
 
stopAction = new QAction(style()->standardIcon(QStyle::SP_MediaStop), tr("Stop"), this);
stopAction->setDisabled(true);
 
connect(playAction, SIGNAL(triggered()), mediaObject, SLOT(play()));
connect(pauseAction, SIGNAL(triggered()), mediaObject, SLOT(pause()) );
connect(stopAction, SIGNAL(triggered()), mediaObject, SLOT(stop()));
 
setupUi();
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::SetFile(const QString& file)
{
source = Phonon::MediaSource(file);
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::StopPlay()
{
mediaObject->stop();
mediaObject->clearQueue();
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::SetUrl(const QUrl &url)
{
source = Phonon::MediaSource(url);
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::playNow()
{
mediaObject->stop();
mediaObject->clearQueue();
 
mediaObject->setCurrentSource(source);
mediaObject->play();
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
{
switch (newState) {
case Phonon::ErrorState:
if(mediaObject){
if (mediaObject->errorType() == Phonon::FatalError) {
QMessageBox::warning(this, tr("Fatal Error"),
mediaObject->errorString());
} else {
QMessageBox::warning(this, tr("Error"),
mediaObject->errorString());
}
}else{
QMessageBox::warning(this, tr("Error"),tr("Media is NULL"));
}
break;
case Phonon::PlayingState:
mStatusLabel->setText("PlayingState");
playAction->setEnabled(false);
pauseAction->setEnabled(true);
stopAction->setEnabled(true);
break;
case Phonon::StoppedState:
mStatusLabel->setText("StoppedState");
stopAction->setEnabled(false);
playAction->setEnabled(true);
pauseAction->setEnabled(false);
timeLcd->display("00:00");
break;
case Phonon::PausedState:
mStatusLabel->setText("PausedState");
pauseAction->setEnabled(false);
stopAction->setEnabled(true);
playAction->setEnabled(true);
break;
case Phonon::BufferingState:
mStatusLabel->setText("BufferingState");
break;
default:
break;
}
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::setBufferingValue(int value)
{
QString statt = "Buffering: " + QString::number(value);
mStatusLabel->setText(statt);
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::sourceChanged(const Phonon::MediaSource& /*source*/)
{
mStatusLabel->setText("sourceChanged");
timeLcd->display("00:00");
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::tick(qint64 time)
{
QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
 
timeLcd->display(displayTime.toString("mm:ss"));
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::aboutToFinish()
{
emit backButtonPressed();
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void MyPlayerView::setupUi()
{
mStatusTitle = new QLabel(tr("Status:"));
mStatusLabel = new QLabel();
 
dummy = new QWidget();
dummy->setDisabled(true);
 
videoWidget = new Phonon::VideoWidget(dummy);
Phonon::createPath(mediaObject, videoWidget);
 
QHBoxLayout *topLayout1 = new QHBoxLayout;
topLayout1->addWidget(mStatusTitle);
topLayout1->addWidget(mStatusLabel);
 
QToolBar *bar = new QToolBar;
bar->addAction(playAction);
bar->addAction(pauseAction);
bar->addAction(stopAction);
 
QPalette palette;
palette.setBrush(QPalette::Light, Qt::darkGray);
timeLcd = new QLCDNumber;
timeLcd->setPalette(palette);
 
volumeSlider = new Phonon::VolumeSlider(this);
volumeSlider->setAudioOutput(audioOutput);
volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(topLayout1);
mainLayout->addWidget(bar);
mainLayout->addWidget(volumeSlider);
mainLayout->addWidget(timeLcd);
setLayout(mainLayout);
}

The sizeHint() method defines the initial size of the widget. The basic handling on getting the stream to play is to construct Phonon::AudioOutput() and Phonon::MediaObject() and linking them together with Phonon::createPath() function call

audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
mediaObject = new Phonon::MediaObject(this);
Phonon::createPath(mediaObject, audioOutput);

The {{Icode|playNow()} function first stop the playing media file, clear the queue, set the current selected source or media and finally starts playing the media object. Which after the file/stream can be played by giving the filename/stream-Url to the media object as a media source and then simply calling play for the media object.

source = Phonon::MediaSource(url);
mediaObject->setCurrentSource(source);
mediaObject->play();

This works fine for file playing, for streams this would most often cause memory violation error, caused by the fact that the streaming back-end implementation often requires Video widget to be also set for the media object. For normal audio streaming the video UI would be unwanted feature, thus to ignore it, you can simply construct it with a parent widget that is disabled:

dummy = new QWidget();
dummy->setDisabled(true);
 
videoWidget = new Phonon::VideoWidget(dummy);
Phonon::createPath(mediaObject, videoWidget);

This way you can play audio parts from all supported video and audio streams. In StopPlay() we stop the currently playing media and then clear the queue. With SetUrl() we set the link to the media source that we want to stream. stateChanged() helps us to check the status of the Phonon Media Playback, from this we can know whether the audio is playing, stopped, pushed, buffering or even there is any error in the file or not. In sourceChanged() function we reset the time of the media playing to zero. setBufferingValue() displays the buffering value in the screen. tick() displays the time in LCD format.

HttpWindow Class Definition

#ifndef MYHTTPWINDOW_H_
#define MYHTTPWINDOW_H_
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QHttp>
#include <QFile>
#include <QProgressDialog>
#include <QListWidget>
#include <QPushButton>
struct MyDataItem
{
QString audio;
QString title;
};
class HttpWindow : public QWidget
{
Q_OBJECT
public:
HttpWindow();
public slots:
void itemSelected(QListWidgetItem *item);
void PlayFile();
signals:
void streamSelected(QString);
 
private:
void addTestData();
private:
QList<MyDataItem> items;
QListWidget* listWidget;
QPushButton* pushBut;
};
#endif /* MYHTTPWINDOW_H_ */

HttpWindow Class Implementation

#include <QtGui>
#include <QtNetwork>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNodeList>
 
#include "HTTP_window.h"
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

HttpWindow::HttpWindow()
{
listWidget = new QListWidget(this);
 
connect(listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(itemSelected(QListWidgetItem*)));
 
pushBut = new QPushButton("Play", this);
connect(pushBut, SIGNAL(pressed()),SLOT(PlayFile()));
 
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(listWidget);
mainLayout->addWidget(pushBut);
setLayout(mainLayout);
 
addTestData();
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

 
void HttpWindow::addTestData()
{
//Clear items
listWidget->clear();
items.clear();
 
MyDataItem newIttem1;
newIttem1.audio = "rtsp://rm.bbc.co.uk/radio2/r2online_id.rm";
newIttem1.title = "rtsp: r2online_id.rm";
items.append(newIttem1);
 
MyDataItem newIttem5;
newIttem5.audio = "rtsp://rmv8.bbc.net.uk:554/radio1coyopa/radio_1_-_friday_1900.ra";
newIttem5.title = "rtsp: radio_1_-_friday_1900.ra";
items.append(newIttem5);
 
 
MyDataItem newIttem3;
newIttem3.audio = "mms://213.92.19.13/m2o";
newIttem3.title = "mms: m2o";
items.append(newIttem3);
 
MyDataItem newIttem4;
newIttem4.audio = "http://od.netro.ca/netrostream113/voice_demo.wma";
newIttem4.title = "http: voice_demo.wma";
items.append(newIttem4);
 
 
MyDataItem newIttem2;
newIttem2.audio = "rtsp://qt2.netro.ca/princess_54.3gp";
newIttem2.title = "rtsp: princess_54.3gp";
items.append(newIttem2);
 
 
for(int i=0; i< items.count(); i++){
listWidget->addItem(items[i].title);
}
}
 
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void HttpWindow::PlayFile()
{
int selIndex = listWidget->currentRow();
 
if(selIndex >= 0 && selIndex < items.count()){
emit streamSelected(items[selIndex].audio);
}
}
/*
* --------------------------------------------------------------
* --------------------------------------------------------------
*/

void HttpWindow::itemSelected(QListWidgetItem *item)
{
PlayFile();
}

itemSelected() call the PlayFile() function and plays the selected item from the list. PlayFile() fetch the selected item from the list and then emits streamSelected() signal and which calls the playStream() signal, addTestData() crated the list widget of the streaming links.


Source Code

The full example with some example streams is found in: StreamMusicTest.zip

Related Article

Live TV with Qt

This page was last modified on 11 October 2012, at 01:18.
103 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×