PDA

View Full Version : QSlider Update Problem



December
9th September 2006, 11:44
Hi All,

I am fairly new QT, having slowly moved from Windows to Linux, I am now re-writing one of my apps from scratch in QT with KDevelop.

I have writing a program that controls stage / club lighting, and uses a MIDI controller as a tactile interface. In the main I have 8 QSliders that correspond to 8 physical sliders on the MIDI controller. I have a QThread that receives MIDI and then passes a QCustomEvent to the main window for appropriate MIDI messages.

When I move a fader on the MIDI controller, my main form is correctly receiving the messages, but here I have run into a problem. When I use the values that the Event is passing to update the position of the slider.. things are pretty bad. The sliders seem to flicker a lot, and lag behind the physical faders by a fair bit.

Thebit of code that updates the QSlider:


if ( e->type() == 2001 ) { // It must be a DataEvent
d_e = (MyDataEvent *) e;
if( d_e->param() > 80 && d_e->param() < 89 ) { // Playback Slider
slider = lPlaySliders.at( d_e->param() - 80 );
if(slider->value() != d_e->value() )
slider->setValue( d_e->value() );
}
}


e is the event, param and value are integers from the MIDI messages. The range of value and therefor the QSliders is 0 to 127 for now. lPlaySliders is an array containing all the 'playback' sliders in the form.

I though it might be the Event mechanism not keeping up (even though the MIDI messages are not coming in at any crazy rate), but having the Event Handler update the text on a QPushButton with the value instead of moving a slider works as it should.. the number keeps up well with the MIDI.

Anyone have any ideas what could be wrong here? Is QSlider prone to update problems.. is there another component I could use instead?

jacek
9th September 2006, 13:48
even though the MIDI messages are not coming in at any crazy rate
Are you sure? What is the maximum number of messages per second?

How does that data-collecting thread works? Maybe it starves the GUI thread?

December
9th September 2006, 16:55
Well, even if I push the fader up real slow.. say 6 seconds from bottom to top, the same problem occurs.

That would mean around 16 messages per second.The code in the MIDI thread is actually still a bit of a mystery to me.. as its taken from some other o/s projects



void midiThread::run()
{
snd_seq_t *seq_handle;
int npfd;
struct pollfd *pfd;

seq_handle = open_seq();
npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
while (1) {
if (poll(pfd, npfd, 100000) > 0) {
midi_action(seq_handle);
}
}
}


This is the run part of the QThread. The other relevant bit is:



void midiThread::midi_action(snd_seq_t *seq_handle) {

snd_seq_event_t *ev;
MyDataEvent dataEvent(0,0);

do {
snd_seq_event_input(seq_handle, &ev);
switch (ev->type) {
case SND_SEQ_EVENT_CONTROLLER:
dataEvent.setParam(ev->data.control.param);
dataEvent.setValue(ev->data.control.value);
QApplication::sendEvent( parent, &dataEvent );
break;
}

snd_seq_free_event(ev);
} while (snd_seq_event_input_pending(seq_handle, 0) > 0);

}


If this is a horrible way to do things.. I would much appreciate any ideas on how to handle MIDI better.

On windows I used Borland C++ Builder.. and found a great component that pretty much did it all for me, passing the messages to my callback function. I guess I have to learn more C++ to program on Linux ;-)

jacek
9th September 2006, 17:25
That would mean around 16 messages per second.
Then it shouldn't be a problem, unless you do a busy-wait somewhere. You check with top if your program doesn't eat whole CPU power.

poll() is a good way to go, but in midi_action() you have a problem --- you use sendEvent(), but only postEvent() is thread-safe.

Try:

void midiThread::midi_action(snd_seq_t *seq_handle) {
...
do {
snd_seq_event_input(seq_handle, &ev);
switch (ev->type) {
case SND_SEQ_EVENT_CONTROLLER:
MyDataEvent *dataEvent = new MyDataEvent(0,0);
dataEvent.setParam(ev->data.control.param);
dataEvent.setValue(ev->data.control.value);
QApplication::postEvent( parent, dataEvent ); // QApplication takes ownership of the event
break;
}
...

December
10th September 2006, 04:02
Wow, that was the problem.

Changing from using sendEvent to postEvent solved it. I feel stupid now, I even remember reading that sendEvent is not thread safe a while back :o

Thanks for the help.. I think QT is going to be a lot of fun with such knowledgeable people around :)