PDA

View Full Version : QThread Sound and Vibrate and Crashing



javed_alam786
21st March 2011, 14:31
Hi All,

I am trying to start three threads,

First Thread need to run constantly at least once in every 3 secs. Once Button1
Second Thread is supposed to play Sound on button click
Third Thread is supposed to vibrate the handset (Nokia E52) on button click.

now 2nd and 3rd thread must run at the same time so that user gets sound and vibration feedback at the same time.

Issue 1: Sound does not play at all. (Vibration works fine)
Issue 2: Application crashes on second button click event.

Please help i have been banging my head on this for a while now.

Kind Regards
Javed


UI
---------------------------
- Button 1 -
- Button 2 -
- Button 3 -
---------------------------

QThread1.pro


SOURCES += main.cpp\
mainwindow.cpp \
VibrateThread.cpp \
ConstThread.cpp \
SoundThread.cpp

HEADERS += mainwindow.h \
SoundThread.h \
ConstThread.h \
VibrateThread.h

FORMS += mainwindow.ui

QT += network
CONFIG += mobility
MOBILITY += feedback



MainWindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QDialog>
#include <QTextEdit>

#include <ConstThread.h>
#include <SoundThread.h>
#include <VibrateThread.h>


namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
virtual ~MainWindow();

ConstThread *objConstThread;
SoundThread *objSoundThread;
VibrateThread *objVibrateThread;

private slots:

void on_btn1_clicked();

void on_btn2_clicked();

void on_btn3_clicked();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


MainWindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QtCore/QCoreApplication>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{

}

void MainWindow::on_btn1_clicked()
{
//Start Thread, must run till the application is running
objConstThread = new ConstThread();
objConstThread->IsLive = true;
objConstThread->start();

ui->btn1->setEnabled(false);
}

void MainWindow::on_btn2_clicked()
{
objSoundThread = new SoundThread("1.wav");
objSoundThread->start();

objVibrateThread = new VibrateThread(500, 1);
objVibrateThread->start();
}

void MainWindow::on_btn3_clicked()
{
objSoundThread = new SoundThread("2.wav", "3.wav");
objSoundThread->start();

objVibrateThread = new VibrateThread(500, 2);
objVibrateThread->start();
}



ConstThread.h


#ifndef CONSTTHREAD_H
#define CONSTTHREAD_H

#include <QTextEdit>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>

class ConstThread: public QThread
{
public:
ConstThread();
void run();

bool IsLive;
};

#endif // CONSTTHREAD_H


ConstThread.cpp


#include "ConstThread.h"

ConstThread::ConstThread()
{
}

void ConstThread::run()
{
qint64 counter = 0;

while (IsLive == true)
{
counter++;
if ((counter%100) == 0)
{
counter = 0;
// do somthing
}
else
{
//do somthing
}

this->msleep(3000);
}
}


SoundThread.h


#ifndef SOUNDTHREAD_H
#define SOUNDTHREAD_H

#include <QTextEdit>
#include <QSound>
#include <QTime>

#include <QThread>
#include <QMutex>
#include <QWaitCondition>

class SoundThread: public QThread
{
public:
SoundThread(QString wavFileName1Val);
SoundThread(QString wavFileName1Val, QString wavFileName2Val);
void run();

QString wavFileName1;
QString wavFileName2;
};

#endif // SOUNDTHREAD_H


SoundThread.cpp


#include "SoundThread.h"

SoundThread::SoundThread(QString wavFileName1Val)
{
wavFileName1 = wavFileName1Val;
wavFileName2 = "";
}

SoundThread::SoundThread(QString wavFileName1Val, QString wavFileName2Val)
{
wavFileName1 = wavFileName1Val;
wavFileName2 = wavFileName2Val;
}

void SoundThread::run()
{

QMutex dummy;
QMutexLocker locker(&dummy);
QWaitCondition waitCondition;

QSound::play("C:\\Data\\Sounds\\TennisMobile\\AdvantageReceiver. wav");
if (wavFileName2 != "")
{
//All sound are 1sec long
waitCondition.wait(&dummy, 1010);
QSound::play("C:\\Data\\Sounds\\TennisMobile\\Let.wav");
}
this->msleep(2000);
}


VibrateThread.h


#ifndef VIBRATETHREAD_H
#define VIBRATETHREAD_H

#include <qmobilityglobal.h>
#include <qfeedbackActuator.h>
#include <qfeedbackeffect.h>
#include <qfeedbackplugininterfaces.h>

#include <QTextEdit>

#include <QSound>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>

class VibrateThread: public QThread
{
public:
VibrateThread(int msecVal, int noOfVibsVal);
void run();

qint32 qintMSec;
qint8 qint8NoOfVibs;
qint16 qint16Interval;

QtMobility::QFeedbackHapticsEffect rumble;
QtMobility::QFeedbackActuator *vibra;
};

#endif // VIBRATETHREAD_H


VibrateThread.cpp


#include "VibrateThread.h"

VibrateThread::VibrateThread(int msecVal, int noOfVibsVal)
{
qintMSec = msecVal;
qint8NoOfVibs = noOfVibsVal;
qint16Interval = 100;

QList<QtMobility::QFeedbackActuator *> list = QtMobility::QFeedbackActuator::actuators();

vibra = 0;

foreach(QtMobility::QFeedbackActuator *a, list)
{
if(a->name() == "Vibra")
vibra = a;
}

if (vibra == 0)
{ }
}

void VibrateThread::run()
{
rumble.setIntensity(1.00);
rumble.setDuration(qintMSec);
rumble.setActuator(vibra);
rumble.start();
this->msleep(qintMSec);
this->msleep(100);//wait msec between two vibrations

for (int count = 1 ; count < qint8NoOfVibs ; count++)
{
rumble.start();
this->msleep(qintMSec + 100); //vibration time + wait time before second vibration
}

this->wait();
}


main.cpp


#include "mainwindow.h"

#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

MainWindow mainWindow;

#if defined(Q_WS_S60)
mainWindow.showMaximized();
#else
mainWindow.show();
#endif

return app.exec();
}


mainwindow.ui


<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>179</width>
<height>138</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="btn2">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>151</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Button 2 Sound &amp; Vibrate</string>
</property>
</widget>
<widget class="QPushButton" name="btn3">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>151</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Button 3 Sound &amp; Vibrate</string>
</property>
</widget>
<widget class="QPushButton" name="btn1">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>151</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Button 1 Looper</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>179</width>
<height>21</height>
</rect>
</property>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

high_flyer
21st March 2011, 15:42
Issue 1: Sound does not play at all. (Vibration works fine)
If you use the code for sound playing in a simple test application which does only that, does it work?
What does QSound::isAvailable () return?


Issue 2: Application crashes on second button click event.
On what line?

This:

objSoundThread = new SoundThread("1.wav");
objSoundThread->start();

objVibrateThread = new VibrateThread(500, 1);
objVibrateThread->start();

is spawning 2 new threads every time you click a button.
Where do you destroy the thread objects?

javed_alam786
21st March 2011, 15:54
Yes Sound plays alright in test application.

I thought thread will terminate itself once it has finished the execution. (Forgive me if i am wrong. I am 2 weeks old for Qt)

high_flyer
21st March 2011, 16:00
I thought thread will terminate itself once it has finished the execution. (Forgive me if i am wrong. I am 2 weeks old for Qt)
This has nothing to do with Qt but basic C/C++.
The thread will terminate, but the thread object which you allocated with 'new' needs to be symmetrically deleted with 'delete' otherwise you have a memory leakage.


Yes Sound plays alright in test application.
Ok, next stage would be to put the playing code directly in the slot, not in a thread, see if gets played then.

wysota
21st March 2011, 17:04
Why are you using threads?

high_flyer
21st March 2011, 17:05
Why are you using threads?
Heh... I didn't even want to go there...
But I agree - sounds like QTimer could do just find here.

wysota
21st March 2011, 17:07
Heh... I didn't even want to go there...
Well, asking about threads is usually my first question as most of the time getting rid of threads also solves the main problem (like crashing).

high_flyer
21st March 2011, 17:09
True.
My assumption was that he needed threads because he wanted vibrating and playing sound in parallel.

wysota
21st March 2011, 17:16
QSound works asynchronously and I'm assuming the feedback API is also asynchronous so no threads are required.

javed_alam786
21st March 2011, 17:46
Reason for using thread is basically, if the user clicks on another button while the first batch of sound and vibration is still running, then it should stop immediately and play the sound and vibration associated with second button.

high_flyer
21st March 2011, 17:50
So just use QSound::stop() on it in the slot of the other button.

javed_alam786
21st March 2011, 18:01
ok. but is there is no a similar function to stop vibration. In fact as far as i know vibration feedback does only one vibration at a given time, I have created 12 distinct vibration patterns with varying intensity and no of vibration and duration. These vibration are associated to each Ui.Button and Keypad used as hotkeys. Idea was to put them in separate threads and kill the thread whenever required.

In the meantime i will try to dump Sound thread and use as u suggested QSound::stop() and see how it goes.

wysota
21st March 2011, 18:16
You can just interrupt your pattern. The fact that you start the first item in the pattern doesn't mean you have to replay it until the end.

javed_alam786
22nd March 2011, 17:55
Hi All,

Thanks you all for directions. I have now manage to handle every issue nicely. I am sure it can be done in a better way but at the moment i am sorted.

I playing sound asynchronously within the calling method. Vibrations is still done in separate thread because of varying different vibration patterns.

Thanks you all very much.

Kind Regards,
Javed