PDA

View Full Version : QThread and QProcess problem



codebehind
30th July 2007, 22:48
I've make a player with a playlist. For playing songs i'm using "play" which i start in a QProcess which runs inside the QThread. The code looks like this:

jBoxPlayer::jBoxPlayer(QListBox *&playlist)
{
_pPlayList = playlist;
_pPlayer = new QProcess(0,"jPlayer");
}

jBoxPlayer::~jBoxPlayer()
{
_pPlayList=NULL;
delete _pPlayer;
}

void jBoxPlayer::run()
{
QLBItemExt *lb;
int i=0;

while (1)
{
// qDebug(QString("loop"));
if ((_pPlayList->count()==0) || _pPlayer->isRunning()) continue;
// if (_pPlayList->count()>0) {QString("if Playlist.");}
// if ( _pPlayer->isRunning()) continue;


qDebug("Playing new song.");
_pPlayer->clearArguments();
lb = (QLBItemExt *)_pPlayList->item(i++);
_pPlayer->addArgument("play");
qDebug(QString("Playing: %1").arg(lb->GetPath()));
_pPlayer->addArgument(lb->GetPath());
lb=NULL;
// mutex.lock();
// _pPlayList->removeItem(0);
// mutex.unlock();
_pPlayer->start();
//_bPlaying=true;
qDebug("loop end.");
}
qDebug("i'm out");
}

the playlist is populated whit 2 songs. When i run the app the player plays well the first song. but when finished playing it throw an segmentation fault. The problem is when i uncoment the line 20,22,23 and comment line 21 it works fine - whitout the segmentation fault.
i have no experience with QThreads and QProcess and i don't know if the while(1) is the right approach (the signal processExited() it should be a better way i think) for the player to play untill the end of the playlist.

Any help on pointing me to the right direction would be great. or how in the real world threads and process are handled

marcel
30th July 2007, 23:04
Well, you have to consider a few things. Like, what if the user presses stop? Then you need to stop the thread.



i have no experience with QThreads and QProcess and i don't know if the while(1) is the right approach (the signal processExited() it should be a better way i think) for the player to play untill the end of the playlist.

For beginning, you should add a flag in the thread( a boolean member) and a setter for it.
Instead of the infinite loop, you should test that flag. You set it to false when the user presses stop.

As for the loop, it is better to put the thread to sleep if it has nothing to do, instead of "continue".

Regarding the playlist:
First note: do not pass a widget, instead pass a list containing the items in the list.
Widgets should be handled only by the GUI thread. Even if you don't modify it, it's still bad practice.
The list should be a pointer in the GUI thread. This structure should get updated if the user adds/removes something from the playlist. Use a mutex to synchronize the threads on that structure( The gui writes, and the player reads the list).

How does it exactly work? You remove items as they are finished playing?
You get a segmentation fault because you're trying to access a list item that does not exist.
That is done in the 28 of the code you posted.

Instead of the tests you do already, why don't you test if "i" is greater than the number of items in the list. If it is, then sleep( you played them all ). Otherwise, play the item at position i.


Regards

codebehind
31st July 2007, 18:50
How does it exactly work? You remove items as they are finished playing?
You get a segmentation fault because you're trying to access a list item that does not exist.
That is done in the 28 of the code you posted.
first idea was to delet each song that was plaied. The seg. fault was throwen before the line 26 (the message has not been written to stdout)


First note: do not pass a widget, instead pass a list containing the items in the list.
Should i use the QMap or some c++ countainers? Do i have to override the update function and compare the contest of "mylist" and the playlist?

put the thread to sleep - you mean for n seconds or is there a way for wake the thread up?

at the end.. thank's for showing me the approach

marcel
31st July 2007, 19:53
first idea was to delet each song that was plaied. The seg. fault was throwen before the line 26 (the message has not been written to stdout)

it doesn't make any sense segfaulting at that location since yoiu basically do the same thing. BTW, what's with "QString("if...")" ?


Should i use the QMap or some c++ countainers? Do i have to override the update function and compare the contest of "mylist" and the playlist?
You can use whatever structure seems fit to you. A QMap is OK, as long as you update it to reflect the widget's content.



put the thread to sleep - you mean for n seconds or is there a way for wake the thread up?


No, you just call QThread::msleep in case the thread has no work to do( i.e. no songs in playlist ). You currently continue the loop. If you use this strategy and look at the processor utilization while no songs in list, then you will see it will be at 100%.

Regards

codebehind
31st July 2007, 20:11
it doesn't make any sense segfaulting at that location since yoiu basically do the same thing. BTW, what's with "QString("if...")" ?
I have no answer for that. QString("") shoul be qDebug("") my mistake...
the problem with segfault is a past... the sleeping thread was successful.

for now my code look like that:


while(playlist>0) // in the future will be a QMap or a FIFO list
{
if (player->isRunning())
{
sleep(n);
continue;
}
// do something with the song while mutex is locked
}

till now i don't have any problem.

marcel
31st July 2007, 20:16
ok then.

Regards

codebehind
31st July 2007, 20:41
i was reading the background of how to implement the communication between queue and the playlist...
i thought to code like that


update()
{
// do the stuff with playlist and the queue
update();
}

or am i missing something?

marcel
31st July 2007, 20:53
Of who's update are you talking about? The list box?

I was thinking more like: you have a list of songs( QList, whatever). This should behave like an external model for the list box. That is when you add an item, you update the list, and as a result of this the widget will get updated also.

You should have a few functions for accessing the list's contents.
Reading and writing to the list should be guarded with a mutex.

You also could add a remove item function which you *call* from the thread when the current song ends. By call I mean emitting a signal from the thread.

But I guess there are other methods. You should choose the one that feels more scalable to you, since I assume your application is just at its beginning, and it will get more complex.

Regards

codebehind
31st July 2007, 21:09
I was talking about the update of the main widget but i haven't thought about the signal and slot way of communication...
i haven't worked with that (excluding the tutor of course) so i'll try it... something new to experiment. it sounds interesting.

marcel
31st July 2007, 21:11
This is the way it is recommended to be done in Qt4. Should work in 3 also.

BTW, why don't you switch to v4? It has a lot of new things...Can't even be compared to 3.

Regards

codebehind
31st July 2007, 21:40
i really don't know. i haven't read the specification for the minimum HW that it works on??
i have a 900 MHz Duron and 512 MB RAM
at my job i have a 3GHz and 1GB RAM and working with vs2005 and it is slow!

marcel
31st July 2007, 21:46
i really don't know. i haven't read the specification for the minimum HW that it works on??
i have a 900 MHz Duron and 512 MB RAM
at my job i have a 3GHz and 1GB RAM and working with vs2005 and it is slow!

Slow in what way? When you compile Qt4 apps? I think it can't get better than that.
My last Qt project( at work ), was taking about 15-20 minutes to compile, on a similar computer( 3ghz, 2gb mem). But it was pretty big.

Ultimately your application's requirements dictate the resources to use.
Qt4 is in many ways faster than 3.


Regards

codebehind
31st July 2007, 22:04
slow in the way of working with it! a few open windows and let say two studios and explorer and IBrowser (Firefox), task manager and a DB Tool (AQT) and MicrosoftExchange... and it needs some time to change between app. That i mean for slow. compile time is fast in front of switching betwin app.

anyway i started to download Qt4, will see!

jpn
7th August 2007, 08:11
Why separate thread? Usually there is no need to execute an external process in a separate thread because it doesn't block anyhow.