PDA

View Full Version : newbe question about signals / slots



Walsi
19th April 2007, 14:33
Hello!

At first a have to say:

.) i am a newb at writing programs in C++
.) i am a newb at Qt
.) i am a newb at OOP

My question: How can I emit a signal out from another function? I think that i have to tedliver someting about the parameters of the functin????

Imagine: I have a SIP Client in C++ (pjsip.org) and I want to build a Application (GUI) on this Client.

So when I (the SIP Client) is called, it comes to a callback function in which the call is handeld. Now i want to see it on the GUI when I get called.

My idea: I program a signal Slot unit:
Signal: --> is in the Callback function --> incomingCall();
and in the Slot: --> I enable some buttons for example.


#include "uscinterface.h" <-- here in this include it the prototyp of the class which contains the signal

static void on_incoming_call(...)
{
...
...
...


emit incomingCallsignal();
}

Error message at compiling:

error: 'incomingCallsignal' was not declared in this scope


So what is my mistake, or what is the right way to solve this problem
If you need more information or sourcecode to help me, let me know

Best Regards,...

marcel
19th April 2007, 14:37
First of all, signals can only be emitted from objects that inherit QObject.
You should take a look in the Assistant at "Signals and slots" before starting anything.

Walsi
19th April 2007, 15:07
Thanks for your quick answer marcel!

I read the information about Signals and Slots in the Assistant again, and now I understand it better. So my I idea to solve this porblem isn't possible.

So, how can I "connect" this Callback function with any element of my GUI???

I am quite desperate about this problem because I am already working about 4 days on it's solution.

So it would be very nice if you could help me!

best Regards,...

marcel
19th April 2007, 15:13
The callback is called from another application or from the same application?

high_flyer
19th April 2007, 15:27
.) i am a newb at writing programs in C++
.) i am a newb at Qt
.) i am a newb at OOP

Welcome!

Look, if you are new to all three, starting with call back functions is a bit hard.
Maybe you don't even need that.
Explain what it is you what to do, maybe the solution is much simpler.

Walsi
19th April 2007, 15:40
I use the PJSIP Opensource. This is a SIP Client without a GUI.

There is a good online support on pjsip.org. There is also an example c file which shows how you could start building your own Applicaiton own it.

I have to build a Application with a GUI (QT4) on it. So I took those sample c file and started modifying and extending it.

There is a callbackfunction which is called when somebody want to call me!


/* Callback called by the library upon receiving incoming call */
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata)
{
pjsua_call_info ci;

PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);

pjsua_call_get_info(call_id, &ci);

PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
(int)ci.remote_info.slen,
ci.remote_info.ptr));

/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
emit incomingCall();
}

I know that the application comes to this function when I get called.

So my first idea was, to rewrite this function so, that it doesn't automatically answer a incoming call but gives any signal to the GUI that I (the user) can see that I am called.

And afterwards I want to press to button and answer this call.


Best Regards,...

high_flyer
19th April 2007, 15:54
Thie issue (external callback and Qt) has been dicussed here quite a bit.
So the basic possiblities are in these threads.
Read a bit, and ask if you need clarifications.
http://www.qtcentre.org/forum/search.php?searchid=61976

Walsi
20th April 2007, 06:18
Sorry - no matches. Please try some different terms.

That comes when i use your link - http://www.qtcentre.org/forum/search.php?searchid=61976


??? STRANGE ???


Instead I read and try to understand this thread: http://www.qtcentre.org/forum/f-qt-programming-2/t-callback-api-and-qt-signalslot-5998.html


Best Regards...

wysota
20th April 2007, 06:30
No, it's not strange. Search results are cached for a limited period of time and it just fell out of cache. It's better to give the URL including search terms instead of the result id. I guess the term was probably "callback".

Walsi
20th April 2007, 06:42
wysota wrote in this thread:


You might register a callback from the callback api and there either call the slot directly or use a dummy QObject that will emit the signal for you.

Is that the right way to handle my problem?

wysota
20th April 2007, 07:05
I have no idea, because I don't know what your problem is :) Looks like it's something different than what the quoted sentence was about.

Walsi
20th April 2007, 07:48
I think it is the same, I want to emit a signal, when callback function from my SIP client (non Qt, only C++) is called.

How can I do this?

marcel
20th April 2007, 07:53
In the Qt app, the callback will be a static function. Given this, you cannot emit a signal from this function when it is called ( it is static, non-QObject ), but you can call a function from the interface ( you will have to make possible the access to the main window or another widget from this callback ). Another solution would be QApplication:: postEvent to post an event that when received by the app will answer the phone or whatever....

Regards

Walsi
20th April 2007, 08:39
Okay that sounds good! I try if understand it in the right way:

I call a function in the callback function from the PJSIP (on_incoming_Call);
This function has access to any Widget or to the main window of Qt;
And in this Function I emit a signal;

Have a look at my Pseudo Source Code

uscsippart.cpp: This is the file where the Callbackfunctions of PJSIP are. This callback function is called when someona calls me. And in this function a call another function (incomingCallFunc).


/* Callback called by the library upon receiving incoming call */
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata)
{
pjsua_call_info ci;

PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);

pjsua_call_get_info(call_id, &ci);

PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
(int)ci.remote_info.slen,
ci.remote_info.ptr));

/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
incomingCallFunc();
}

uscinterface.h: here is a "DummyObject" which should has a signal and further here is the prototyp of the function incomingCallFunc();


#ifndef INTERFACE_H
#define INTERFACE_H

#include <QObject>

class IncomingCall : public QObject
{
Q_OBJECT

public:
IncomingCall(QObject *parent = 0);


signals:
void incomingCallsignal();
};

void incomingCallFunc(void);
#endif


uscinterface.cpp: looks like this!



#include "uscinterface.h"

IncomingCall::IncomingCall (QObject *parent)
: QObject(parent)
{
}

void incomingCallFunc()
{
// QT Code to emit a signal
}

uscgui.h:


#ifndef USCGUI_H
#define USCGUI_H

#include <QWidget>

class QLabel;
class QPushButton;

class UscGuiES01 : public QWidget
{
Q_OBJECT

public:
UscGuiES01(QWidget *parent = 0);

signals:

private slots:

void makeCall();
void incomingCall();
private:
QLabel *statusLabel;
QPushButton *acceptButton;
QPushButton *hangupButton;
QPushButton *dialButton;
};

class UscStatusDisplay : public QWidget
{
Q_OBJECT

public:
UscStatusDisplay(QWidget *parent = 0);
};
#endif

and now uscgui.cpp: Here I generate my GUI I connect Signals and Slots.


#include <pjlib.h>
#include <pjlib-util.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pjsip.h>
#include <pjsip_simple.h>
#include <pjsip_ua.h>
#include <pjsua-lib/pjsua.h>

#include <QtGui>
#include "uscgui.h"
#include "uscinterface.h"

UscGuiES01::UscGuiES01(QWidget *parent)
: QWidget(parent)
{

statusLabel = new QLabel(tr("???"));

dialButton = new QPushButton(tr("Dial"));

acceptButton = new QPushButton(tr("Accept"));
acceptButton->setDefault(true);
acceptButton->setEnabled(false);

hangupButton = new QPushButton(tr("Hang Up"));
hangupButton->setEnabled(false);

UscStatusDisplay *uscGuiStatusDisplay = new UscStatusDisplay;
IncomingCall *incomingCall = new IncomingCall;


/*
Insert here the connections for the Signals and Slots
System
*/

connect(dialButton, SIGNAL(clicked()),
this, SLOT(makeCall()));

connect(incomingCall, SIGNAL(incomingCallsignal()),
this, SLOT(incomingCall()));

QHBoxLayout *bottomLayout = new QHBoxLayout;
bottomLayout->addWidget(dialButton);
bottomLayout->addWidget(acceptButton);
bottomLayout->addWidget(hangupButton);

QHBoxLayout *topLayout = new QHBoxLayout;
topLayout->addWidget(statusLabel);
topLayout->addWidget(uscGuiStatusDisplay);

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(topLayout);
mainLayout->addLayout(bottomLayout);
setLayout(mainLayout);

setWindowTitle(tr("Universal SIP Client"));

emit
}
/*
Insert here the SLOT Functions
*/

void UscGuiES01::makeCall()
{
pj_str_t uri = pj_str("sip:nb100149@10.17.1.17");
pjsua_call_make_call(0, &uri, 0, NULL, NULL, NULL);
}

void UscGuiES01::incomingCall()
{
acceptButton->setEnabled(true);
hangupButton->setEnabled(true);
}

UscStatusDisplay::UscStatusDisplay(QWidget *parent)
: QWidget(parent)
{
setPalette(QPalette(QColor(Qt::green)));
setAutoFillBackground(true);
}



Now I want to emit the signal of the class Incomingcall(uscinterface.h) by the function incomingCallFunc() in uscinterface.cpp. but I don't now how??

Or, another possibility, I want to set in this function the Buttons (accept, hangup) enabled and leave the signals and slots out for this part.

So, how can I implement that this function has access to the widget (uscgui.cpp)


I have no idea? :confused: :confused:

Best Regards...

wysota
20th April 2007, 08:49
I think your situation is completely different. You just want to access a method (emit a signal) from an object you don't have a pointer to. Just make the pointer available somewhere so that the callback can access it and that's it. You don't need any special external or additional objects or any other kind of special treatment.

marcel
20th April 2007, 09:18
Yes, juts call the slot from the interface in incomingCallFunc. No need to emit the signal. Make your main window available in incomingCallFunc and simply call the slot (which now doesn't necessarily needs to be a slot ).

Regards

Walsi
20th April 2007, 09:35
OMG

That really sounds very easy for me. But i think it isn't as easy for me to implement.

Okay, let me try:

I generate a pointer which points to my object usc_gui. This object is created in main.

main.cpp


#include <pjlib.h>
#include <pjlib-util.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pjsip.h>
#include <pjsip_simple.h>
#include <pjsip_ua.h>
#include <pjsua-lib/pjsua.h>

#include <QApplication>

#include "uscsippart.h"
#include "uscgui.h"
#include "uscinterface.h"

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

QApplication uscguiapp(argc, argv);
UscGuiES01 usc_gui;
usc_gui.show();

return uscguiapp.exec();

}

Via the parameters I give the callback function the pointer and in the function I can do anything with the object.

For example:


void incomingCallFunc(Usc_Gui_ES01 *to_usc_gui)
{
*to_usc_gui.acceptButton->setEnabled(true);
*to_usc_gui.hangupButton->setEnabled(true);
}


But where I call this function, the pointer also must be known there?


incomingCallFunc(&to_usc_gui);

Where and how must I define and/or declarate the pointer that it works?

Best Regards,...

wysota
20th April 2007, 10:23
You should really learn a bit of C++... Your problem is strictly programming language related.

Walsi
20th April 2007, 10:25
Okay!!

Many thanks to you!!

I will learn C++!!!

wysota
20th April 2007, 10:54
Please read about scopes and declarations of external variables. This should allow you to solve the problem yourself.