| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 3 | |
In my application I have the following message: QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(011DE140), parent's thread is QThread(011D5420), current thread is QThread(011DC5F0)) QSocketNotifier: Can only be used with threads started with QThread I have the main and then I start a thread in which I have a reference to a QTcpServer ( a pthread which generates event with data that I want to send through a connection with a client?) I try in the application to return a pointer to the QTcpSocket to store it as a global variable usable in other function in the main.cpp because I want to catch data and send them. But I have the error. And the connection is established but I?m not able to send data? because when I call write it gives me the message. The audio_callback is the function used to intercept data in the other thread and that would allow me to send to the client using the socket. I attach my code. Very Thanks in advance. Best regards, Marco Bnà
#include "iaxserverout.h"
#include "iaxserverout.h"
#include "iaxsocketout.h"
#include <iostream>
IaxServerOut::IaxServerOut(QObject *parent)
: QTcpServer(parent)
{
this->socketOut = 0;
}
void IaxServerOut::incomingConnection(int socketId)
{
this->socketOut = new IaxSocketOut(this);
this->socketOut->setSocketDescriptor(socketId);
//connect(this, SIGNAL(newConnection()), this, SLOT(connCreated()));
}
IaxSocketOut* IaxServerOut::getActiveSocket()
{
return this->socketOut;
}
int IaxServerOut::sendViaActiveSocket(const char* data, int size, int format)
{
return this->socketOut->process_and_send(data, size, format);
}
//void IaxServerOut::connCreated()
//{
// std::cout << "CONNECTION ESTABLISHED" << std::endl;
//}
IaxServerOut::~IaxServerOut()
{
/**commento questa parte poichè il destroy della
QTcpSocket dovrebbe essere fatto sulla disconnessione
dal client*/
//if (socketOut)
//{
//delete this->socketOut;
//}
}
#ifndef IAXSERVEROUT_H
#ifndef IAXSERVEROUT_H
#define IAXSERVEROUT_H
#include <QObject>
#include <QTcpServer>
#include "iaxsocketout.h"
class IaxServerOut : public QTcpServer
{
Q_OBJECT
public:
IaxServerOut(QObject *parent = 0);
~IaxServerOut();
public:
void incomingConnection(int);
IaxSocketOut* getActiveSocket();
int sendViaActiveSocket(const char*, int, int);
//public slots:
//void connCreated();
private:
int port;
IaxSocketOut* socketOut;
};
#endif // IAXSERVEROUT_H
#include "iaxsocketout.h"
#include "iaxsocketout.h"
#include <iostream>
#include <QTcpSocket>
#include <QDataStream>
#include <iaxclient.h>
#include <samplerate.h>
IaxSocketOut::IaxSocketOut(QObject *parent)
: QTcpSocket(parent)
{
connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
this->stream = new QDataStream(this);
this->stream->setVersion(QDataStream::Qt_4_0);
}
//ritorna 0 se tutto è andato bene altrimenti ritorna un valore diverso da 0
int IaxSocketOut::process_and_send(const char* sound_data, int size, int format)
{
if (format != IAXC_FORMAT_ALAW)
{
return -1;
}
short* short_data = new short[size];
int i;
for (i=0; i < size; i++)
{
short_data[i] = this->alawdecode((unsigned char)(sound_data[i]));
}
float* float_data_in = new float[size];
float* float_data_out= new float[size];
src_short_to_float_array(short_data, float_data_in, size);
SRC_DATA* src_data;
if ( src_data = (SRC_DATA*)malloc(sizeof(SRC_DATA)))
{
src_data->data_in = float_data_in;
src_data->data_out = float_data_out;
src_data->end_of_input = 1;
src_data->input_frames = size;
src_data->input_frames_used = 1;
src_data->output_frames = 1;
src_data->output_frames_gen = 1;
src_data->src_ratio = 2.0;
}
else
{
std::cerr << "Heap memory is full";
return -1;
}
int error = src_simple(src_data, SRC_SINC_BEST_QUALITY, 1);
int written;
if (!error)
{
short* short_data_out = new short[size];
src_float_to_short_array(float_data_out, short_data_out, size);
int greater_size = size*sizeof(short);
char* char_data = new char[greater_size];
int char_data_pos = 0;
for (i=0; i < size; i++)
{
short2char* element = (short2char*)malloc(sizeof(short2char));
element->s = short_data_out[i];
int short_dim = sizeof(short);
for (int curr_char = 0; curr_char < short_dim; curr_char++)
{
char_data[char_data_pos] = element->c[curr_char];
char_data_pos++;
}
free(element);
}
//this->stream->writeRawData(char_data, greater_size);
QByteArray soundArray(char_data, greater_size);
QDataStream stream(&soundArray, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_4_0);
written = (int)this->write(soundArray);
delete[] char_data;
delete[] short_data_out;
}
else
{
return error;
}
free(src_data);
delete[] float_data_out;
delete[] float_data_in;
delete[] short_data;
return written;
}
IaxSocketOut::~IaxSocketOut()
{
}
inline short int IaxSocketOut::alawdecode(unsigned char alaw)
{
int value;
int segment;
/* Mask value */
alaw ^= 0x55;
/* Extract and scale value */
value = (alaw & 0x0f) << 4;
/* Extract segment number */
segment = (alaw & 0x70) >> 4;
/* Compute value */
switch (segment) {
case 0:
break;
case 1:
value += 0x100;
break;
default:
value += 0x100;
value <<= segment - 1;
}
/* Extract sign */
return (alaw & 0x80) ? value : -value;
}#ifndef IAXSOCKETOUT_H
#define IAXSOCKETOUT_H
#include <QTcpSocket>
class IaxSocketOut : public QTcpSocket
{
Q_OBJECT
public:
IaxSocketOut(QObject *parent);
~IaxSocketOut();
public:
int process_and_send(const char*, int , int);
private:
inline short int alawdecode(unsigned char);
private:
QDataStream* stream;
typedef union {
short s;
char c[2];
} short2char;
};
#endif // IAXSOCKETOUT_H
#include <QtCore/QCoreApplication>
#include <QtCore/QCoreApplication>
#include <QHostAddress>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <signal.h>
#include <iaxclient.h>
#include "iaxserverout.h"
#include "iaxsocketout.h"
#define LEVEL_INCREMENT 0.10f
/* static int answered_call; */
static char *output_filename = NULL;
static char *username = "skypetest";
static char *password = "skypetest";
static char *host = "10.15.8.9";
int do_levels = 0;
int intercom = 0;
int initialized = 0;
int reg_id = 0;
IaxSocketOut* socketout = NULL;
IaxServerOut* server = NULL;
/* routine called at exit to shutdown audio I/O and close nicely.
NOTE: If all this isnt done, the system doesnt not handle this
cleanly and has to be rebooted. What a pile of doo doo!! */
void killem(void)
{
if (initialized)
iaxc_shutdown();
if (reg_id){
iaxc_unregister(reg_id);
}
return;
}
void signal_handler(int signum)
{
if ( signum == SIGTERM || signum == SIGINT )
{
killem();
exit(0);
}
}
void fatal_error(char *err) {
killem();
fprintf(stderr, "FATAL ERROR: %s\n", err);
exit(1);
}
void mysleep(void)
{
iaxc_millisleep(10);
}
int state_event_callback(struct iaxc_ev_call_state call){
if((call.state & IAXC_CALL_STATE_RINGING))
{
printf("Receiving Incoming Call Request...\n");
if ( intercom )
{
printf("Intercom mode, answer automatically\n");
return iaxc_select_call(call.callNo);
}
}
return 0;
}
int levels_callback(float input, float output) {
if(do_levels) fprintf(stderr, "IN: %f OUT: %f\n", input, output);
return 0;
}
int netstat_callback(struct iaxc_ev_netstats n) {
static int i;
if(i++%25 == 0)
fprintf(stderr, "RTT\t"
"Rjit\tRlos%%\tRlosC\tRpkts\tRdel\tRdrop\tRooo\t"
"Ljit\tLlos%%\tLlosC\tLpkts\tLdel\tLdrop\tLooo\n"
);
fprintf(stderr, "%d\t"
"%d\t%d\t%d\t%d\t%d\t%d\t%d\t"
"%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
n.rtt,
n.remote.jitter,
n.remote.losspct,
n.remote.losscnt,
n.remote.packets,
n.remote.delay,
n.remote.dropped,
n.remote.ooo,
n.local.jitter,
n.local.losspct,
n.local.losscnt,
n.local.packets,
n.local.delay,
n.local.dropped,
n.local.ooo
);
return 0;
}
int audio_event_callback(struct iaxc_ev_audio e)
{
int toReturn = socketout->process_and_send((char*)e.data, e.size, e.format);
return toReturn;
}
int iaxc_callback(iaxc_event e)
{
switch(e.type) {
case IAXC_EVENT_LEVELS:
return levels_callback(e.ev.levels.input, e.ev.levels.output);
case IAXC_EVENT_NETSTAT:
return netstat_callback(e.ev.netstats);
case IAXC_EVENT_TEXT:
return 0; // don't handle
case IAXC_EVENT_STATE:
return state_event_callback(e.ev.call);
case IAXC_EVENT_AUDIO:
return audio_event_callback(e.ev.audio);
default:
return 0; // not handled
}
}
void list_devices()
{
struct iaxc_audio_device *devs;
int nDevs, input, output, ring;
int i;
iaxc_audio_devices_get(&devs,&nDevs, &input, &output, &ring);
for(i=0;i<nDevs;i++) {
fprintf(stderr, "DEVICE ID=%d NAME=%s CAPS=%lx\n", devs[i].devID, devs[i].name, devs[i].capabilities);
}
}
void usage()
{
fprintf(stderr, "Usage: testcall [-?] [-v] [-i] [-s SILENCE_THRESHOLD] [-u USERNAME -p PASSWORD -h HOST]\n");
exit(1);
}
int main(int argc, char **argv)
{
QCoreApplication a(argc, argv);
server = new IaxServerOut();
server->listen(QHostAddress::LocalHost, 56000);
FILE *f;
char c;
int i;
char *dest = "skypetest:skypetest@xxxxxxxxx/4050";
float silence_threshold = -99.0f;
float level;
f = stdout;
for(i=1;i<argc;i++)
{
if(argv[i][0] == '-')
{
switch(tolower(argv[i][1]))
{
case '?':
usage();
break;
case 'v':
do_levels = 1;
break;
case 'i':
intercom = 1;
break;
case 's':
if(i+1 >= argc) usage();
silence_threshold = (float)atof(argv[++i]);
break;
case 'u':
if(i+1 >= argc) usage();
username = argv[++i];
break;
case 'p':
if(i+1 >= argc) usage();
password = argv[++i];
break;
case 'h':
if(i+1 >= argc) usage();
host = argv[++i];
break;
default:
usage();
}
} else {
dest=argv[i];
}
}
printf("settings: \n");
printf("\tsilence threshold: %f\n", silence_threshold);
printf("\tlevel output: %s\n", do_levels ? "on" : "off");
/* activate the exit handler */
atexit(killem);
/* install signal handler to catch CRTL-Cs */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
iaxc_set_preferred_source_udp_port(4590);
iaxc_set_test_mode(1);
if ( iaxc_initialize(1) ) fatal_error("cannot initialize iaxclient!");
initialized = 1;
// iaxc_set_formats(IAXC_FORMAT_SPEEX,IAXC_FORMAT_ULAW|IAXC_FORMAT_GSM|IAXC_FORMAT_SPEEX);
// iaxc_set_formats(IAXC_FORMAT_SPEEX,IAXC_FORMAT_SPEEX);
iaxc_set_formats(IAXC_FORMAT_ALAW,IAXC_FORMAT_ALAW);
//iaxc_set_formats(IAXC_FORMAT_ULAW,IAXC_FORMAT_ULAW);
//iaxc_set_formats(IAXC_FORMAT_ULAW,IAXC_FORMAT_ILBC|IAXC_FORMAT_ULAW|IAXC_FORMAT_GSM|IAXC_FORMAT_SPEEX);
iaxc_set_silence_threshold(silence_threshold);
//list_devices();
iaxc_set_event_callback(iaxc_callback);
unsigned int prefs = IAXC_AUDIO_PREF_RECV_REMOTE_RAW | IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED;
if (iaxc_set_audio_prefs(prefs) == -1)
exit(1);
/*if(dest) {
fprintf(f, "Calling %s\n", dest);
iaxc_call(dest);
}*/
iaxc_start_processing_thread();
if (username && password && host)
reg_id = iaxc_register(username, password, host);
printf("ready for keyboard input\n");
server->waitForNewConnection(1000000000000);
socketout = server->getActiveSocket();
if(dest) {
fprintf(f, "Calling %s\n", dest);
iaxc_call(dest);
}
return a.exec();
}
//int main(int argc, char *argv[])
//{
// QCoreApplication a(argc, argv);
//
// return a.exec();
//}
Hi, > In my application I have the following message: It would help if could post a *minimal* example that reproduces the problem. -- [ signature omitted ]
I attached the code... Hasn't it arrived? -----Messaggio originale----- Da: Dimitri [mailto:dimitri@xxxxxxxxxxxxx] Inviato: lunedì 12 novembre 2007 21.59 A: qt-interest@xxxxxxxxxxxxx Oggetto: Re: Use of QTcpServer and QTcpSocket between different threads Hi, > In my application I have the following message: It would help if could post a *minimal* example that reproduces the problem. -- [ signature omitted ]
Marco Bnà wrote: >I attached the code... Hasn't it arrived? It did. But we're asking for a *minimal* example. >-----Messaggio originale----- >Da: Dimitri [mailto:dimitri@xxxxxxxxxxxxx] >Inviato: lunedì 12 novembre 2007 21.59 >A: qt-interest@xxxxxxxxxxxxx >Oggetto: Re: Use of QTcpServer and QTcpSocket between different threads > >Hi, > >> In my application I have the following message: > >It would help if could post a *minimal* example that reproduces the > problem. -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
In the main there's variable
IaxSocketOut* socketout = null;
The class IaxSocketOut extends QTcpSocket. The class IaxServerOut extends
QTcpServer and implements
Void incomingConnection(int socketDescriptor)
{
This->socketout = new IaxSocketOut(this);
This->socketout->setSocketDescriptor(socketDescriptor);
}
IaxSocketOut* IaxServerOut::getSocketOut()
{ return sockeout}
Socketout = iaxserver.getSocketOut();
So I save the variable. The connection is started when I launch an app which
simulates a client on the port specified and where the server is listening.
The method iaxc_start_processing_thread() called in main func starts a
thread which is involved in chatching events generated (incoming data from
Asterisk). This method as all other with iaxc is part of IAXClient C
library.
Here is the code iaxc_start_processing_thread func
<code>
#if defined(WIN32) || defined(_WIN32_WCE)
#define THREAD HANDLE
#define THREADID unsigned
#define THREADCREATE(func, args, thread, id) \
(thread = (HANDLE)_beginthreadex(NULL, 0, func, (PVOID)args, 0, &id))
#define THREADCREATE_ERROR NULL
#define THREADFUNCDECL(func) unsigned __stdcall func(PVOID args)
#define THREADFUNCRET(r) int r = 0
#define THREADJOIN(t)
static THREAD main_proc_thread;
#ifdef USE_VIDEO
static THREAD video_proc_thread;
#endif
#if defined(WIN32) || defined(_WIN32_WCE)
static THREADID main_proc_thread_id;
#ifdef USE_VIDEO
static THREADID video_proc_thread_id;
#endif
#endif
EXPORT int iaxc_start_processing_thread()
{
main_proc_thread_flag = 0;
if ( THREADCREATE(main_proc_thread_func, NULL, main_proc_thread,
main_proc_thread_id) == THREADCREATE_ERROR)
return -1;
#ifdef USE_VIDEO
video_proc_thread_flag = 0;
if ( THREADCREATE(video_proc_thread_func, NULL, video_proc_thread,
video_proc_thread_id) == THREADCREATE_ERROR)
return -1;
#endif
return 0;
}
</code>
Iaxc_set_callback_func() registers the function I want to use when a new
event is generated...
Iaxc_callback catch events and gets data. I'm interested in audio_data so I
try to take audio event data in audio_callback function.
Here I call the stored variable method process_and_send which contains a
call to "write" method...
I hope that this explanation will help... I'm not able to do an example
because I use the library and I'm new to this kind of programming...
Best regards.
Marco
-----Messaggio originale-----
Da: Thiago Macieira [mailto:thiago.macieira@xxxxxxxxxxxxx]
Inviato: lunedì 12 novembre 2007 22.10
A: qt-interest@xxxxxxxxxxxxx
Oggetto: Re: R: Use of QTcpServer and QTcpSocket between different threads
Marco Bnà wrote:
>I attached the code... Hasn't it arrived?
It did. But we're asking for a *minimal* example.
>-----Messaggio originale-----
>Da: Dimitri [mailto:dimitri@xxxxxxxxxxxxx]
>Inviato: lunedì 12 novembre 2007 21.59
>A: qt-interest@xxxxxxxxxxxxx
>Oggetto: Re: Use of QTcpServer and QTcpSocket between different threads
>
>Hi,
>
>> In my application I have the following message:
>
>It would help if could post a *minimal* example that reproduces the
>problem.
--
[ signature omitted ]
Hi Marco,
I'm using sockets in a multithreaded environment - using a socket
in threads is very hard and using one socket by multiple threads
directly not possible, because sockets ARE NOT threadsafe.
So I solved it the following way:
I created a wrapper class for the TcpServer and used a QTcpServer
object ("tcpServer"). My TcpServer uses the signal newConnection()
and sets a QTcpSocket pointer variable with
pSocket = tcpServer->nextPendingConnection()
and connects the signal readyRead() of the pSocket to my read method.
Please DO NOT use incomingConnection() - it's in the Qt examples,
but not the recommended way! Please use the signals instead - they
are threadsafe.
The client sockets are implemented using only signals and a wrapper
class, too.
If you want to have a seperate thread for each client socket,
you MUST create the socket objects in the run() method of the QThread
and connect the signals for readyRead() and after that call the exec()
inside the run() to start the thread's own event loop.
This works great in very heavy industrial envirnments.
ciao,
Chris
--
[ signature omitted ]
> I'll apply as soon as I can your suggestions. For the time being really
> thank you very much!
> I ask you another think... to make the socket write when I have data from a
> function in the main file?
> Is there a way?
Create a slot for writing the data in your socket class and connect
it with a signal - so you just have to emit a signal,
e.g.: emit writeSocketData("Hello World") and the slot gets called
in a thread safe way.
ciao,
Chris
--
[ signature omitted ]
I need to ask you a resume because I think to have not done the right thing
(I pay my inexperience in Qt programming):
1) I need to create a wrapper for QTcpServer... Do you mean to create a
class that has a private member that is a QTcpServer* tcpServer, right?
2) I need to catch the created QTcpSocket -> connect(this->tcpServer,
SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
I defined manage new connection as
Void Wrapper::manageNewConnection()
{
This->socket = this->tcpServer->nextPendingConnection();
}
3) I define a function that when called emits a signal
void callReadyWrite(char* data, int size)
{
emit ReadyWrite(data, size)
}
The slot to which this signal is connected is a function that?s takes
argument and write to the socket...
The problem: doing so I'm not able to catch the socket created... It never
calls manageNewConnection().
What's wrong?
Thank you very much.
Regards,
Marco
-----Messaggio originale-----
Da: Christian Dähn [mailto:daehn@xxxxxxxxxx]
Inviato: mercoledì 14 novembre 2007 18.57
A: qt-interest@xxxxxxxxxxxxx
Oggetto: Re: R: R: Use of QTcpServer and QTcpSocket between different
threads
Hi Marco,
I'm using sockets in a multithreaded environment - using a socket
in threads is very hard and using one socket by multiple threads
directly not possible, because sockets ARE NOT threadsafe.
So I solved it the following way:
I created a wrapper class for the TcpServer and used a QTcpServer
object ("tcpServer"). My TcpServer uses the signal newConnection()
and sets a QTcpSocket pointer variable with
pSocket = tcpServer->nextPendingConnection()
and connects the signal readyRead() of the pSocket to my read method.
Please DO NOT use incomingConnection() - it's in the Qt examples,
but not the recommended way! Please use the signals instead - they
are threadsafe.
The client sockets are implemented using only signals and a wrapper
class, too.
If you want to have a seperate thread for each client socket,
you MUST create the socket objects in the run() method of the QThread
and connect the signals for readyRead() and after that call the exec()
inside the run() to start the thread's own event loop.
This works great in very heavy industrial envirnments.
ciao,
Chris
--
[ signature omitted ]
Hi Marco,
Well a wrapper doesn't mean that you need to have a pointer to
QTcpServer as a private member.
(e.g you can use inheritance). But it is one way to wrap the QTcpServer.
I'm not sure why you do this :
QTcpSocket -> connect(this->tcpServer, SIGNAL(newConnection()), this,
SLOT(manageNewConnection()));
It means you connect a QTcpServer pointer which is a member of the
Wrapper class, but you call the QObject::connect for a QTcpSocket
object. Of course, there is no newConnection() signal in QTcpSocket
You can invoke the manageNewConnection() by writing this:
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
By using that, "this" should be a pointer to the wrapper class.
On Nov 16, 2007 5:43 PM, Marco Bnà <bna.marco@xxxxxxxxx> wrote:
> I need to ask you a resume because I think to have not done the right thing
> (I pay my inexperience in Qt programming):
> 1) I need to create a wrapper for QTcpServer... Do you mean to create a
> class that has a private member that is a QTcpServer* tcpServer, right?
> 2) I need to catch the created QTcpSocket -> connect(this->tcpServer,
> SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
> I defined manage new connection as
>
> Void Wrapper::manageNewConnection()
> {
> This->socket = this->tcpServer->nextPendingConnection();
> }
>
> 3) I define a function that when called emits a signal
>
> void callReadyWrite(char* data, int size)
> {
> emit ReadyWrite(data, size)
> }
>
> The slot to which this signal is connected is a function that's takes
> argument and write to the socket...
>
> The problem: doing so I'm not able to catch the socket created... It never
> calls manageNewConnection().
> What's wrong?
>
> Thank you very much.
>
> Regards,
> Marco
>
I'm sorry, the signal is from this->tcpServer I mean you use QObject::connect inherited in QTcpSocket, but I don't know why you do that. On Nov 16, 2007 6:45 PM, Jesse Armand <mnemonic.fx@xxxxxxxxx> wrote: > Hi Marco, > > Well a wrapper doesn't mean that you need to have a pointer to > QTcpServer as a private member. > (e.g you can use inheritance). But it is one way to wrap the QTcpServer. > > I'm not sure why you do this : > QTcpSocket -> connect(this->tcpServer, SIGNAL(newConnection()), this, > SLOT(manageNewConnection())); > > It means you connect a QTcpServer pointer which is a member of the > Wrapper class, but you call the QObject::connect for a QTcpSocket > object. Of course, there is no newConnection() signal in QTcpSocket > > You can invoke the manageNewConnection() by writing this: > > connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection())); > > By using that, "this" should be a pointer to the wrapper class. > > -- [ signature omitted ]
Exactly... I have a class that have a private member that is a pointer to a QTcpServer that I called tcpServer.
I then do
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
to catch inside it the created QTcpSocket, that I save in a private member that is a pointer to the returned socket.
(e.g. this->socket = this->tcpServer->nextPendingConnection() );
The purpose is to use the socket to write through it an audio stream that I modify using other methods of the class
But I'm not able the catch the created socket. Data comes to me through a library that gives the possibility to define callback
functions. Defining my own callback func in the main file, I would like to call a method of the class that should give the possibility
to send data through the created socket.
I had (and I'll be grateful to have other) suggestion by Christian but, cause my inexperience in Qt programming I thing, I'm not able to solve the problem.
Thanks for the help and I'm grateful to you for the help.
Regards,
Marco
-----Messaggio originale-----
Da: Jesse Armand [mailto:mnemonic.fx@xxxxxxxxx]
Inviato: venerdà 16 novembre 2007 12.46
A: Marco BnÃ
Cc: Christian DÃhn; qt-interest@xxxxxxxxxxxxx
Oggetto: Re: R: R: R: Use of QTcpServer and QTcpSocket between different threads
Hi Marco,
Well a wrapper doesn't mean that you need to have a pointer to
QTcpServer as a private member.
(e.g you can use inheritance). But it is one way to wrap the QTcpServer.
I'm not sure why you do this :
QTcpSocket -> connect(this->tcpServer, SIGNAL(newConnection()), this,
SLOT(manageNewConnection()));
It means you connect a QTcpServer pointer which is a member of the
Wrapper class, but you call the QObject::connect for a QTcpSocket
object. Of course, there is no newConnection() signal in QTcpSocket
You can invoke the manageNewConnection() by writing this:
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
By using that, "this" should be a pointer to the wrapper class.
On Nov 16, 2007 5:43 PM, Marco Bnà <bna.marco@xxxxxxxxx> wrote:
> I need to ask you a resume because I think to have not done the right thing
> (I pay my inexperience in Qt programming):
> 1) I need to create a wrapper for QTcpServer... Do you mean to create a
> class that has a private member that is a QTcpServer* tcpServer, right?
> 2) I need to catch the created QTcpSocket -> connect(this->tcpServer,
> SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
> I defined manage new connection as
>
> Void Wrapper::manageNewConnection()
> {
> This->socket = this->tcpServer->nextPendingConnection();
> }
>
> 3) I define a function that when called emits a signal
>
> void callReadyWrite(char* data, int size)
> {
> emit ReadyWrite(data, size)
> }
>
> The slot to which this signal is connected is a function that's takes
> argument and write to the socket...
>
> The problem: doing so I'm not able to catch the socket created... It never
> calls manageNewConnection().
> What's wrong?
>
> Thank you very much.
>
> Regards,
> Marco
>
--
[ signature omitted ]
Hmmm, so have you solved your problem yet ? If you don't receive any data (the newConnection() signal is not emitted), then maybe you haven't listen() in a specific socket. Call QTcpServer::listen() before you connect the newConnection() signal. Regards, Jesse On Nov 16, 2007 8:28 PM, Marco Bnà <bna.marco@xxxxxxxxx> wrote: > Exactly... I have a class that have a private member that is a pointer to a QTcpServer that I called tcpServer. > I then do > connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection())); > > to catch inside it the created QTcpSocket, that I save in a private member that is a pointer to the returned socket. > > (e.g. this->socket = this->tcpServer->nextPendingConnection() ); > The purpose is to use the socket to write through it an audio stream that I modify using other methods of the class > But I'm not able the catch the created socket. Data comes to me through a library that gives the possibility to define callback > functions. Defining my own callback func in the main file, I would like to call a method of the class that should give the possibility > to send data through the created socket. > I had (and I'll be grateful to have other) suggestion by Christian but, cause my inexperience in Qt programming I thing, I'm not able to solve the problem. > > Thanks for the help and I'm grateful to you for the help. > > Regards, > Marco > > >
I've got it!
Method initServer(int port)
{
This->tcpServer = new TcpServer(this);
This->tcpServer->listen(port);
}
-----Messaggio originale-----
Da: Jesse Armand [mailto:mnemonic.fx@xxxxxxxxx]
Inviato: sabato 17 novembre 2007 10.53
A: qt-interest@xxxxxxxxxxxxx
Oggetto: Re: R: R: R: R: Use of QTcpServer and QTcpSocket between different threads
Hmmm, so have you solved your problem yet ?
If you don't receive any data (the newConnection() signal is not
emitted), then maybe you haven't listen() in a specific socket.
Call QTcpServer::listen() before you connect the newConnection() signal.
Regards,
Jesse
On Nov 16, 2007 8:28 PM, Marco Bnà <bna.marco@xxxxxxxxx> wrote:
> Exactly... I have a class that have a private member that is a pointer to a QTcpServer that I called tcpServer.
> I then do
> connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection()));
>
> to catch inside it the created QTcpSocket, that I save in a private member that is a pointer to the returned socket.
>
> (e.g. this->socket = this->tcpServer->nextPendingConnection() );
> The purpose is to use the socket to write through it an audio stream that I modify using other methods of the class
> But I'm not able the catch the created socket. Data comes to me through a library that gives the possibility to define callback
> functions. Defining my own callback func in the main file, I would like to call a method of the class that should give the possibility
> to send data through the created socket.
> I had (and I'll be grateful to have other) suggestion by Christian but, cause my inexperience in Qt programming I thing, I'm not able to solve the problem.
>
> Thanks for the help and I'm grateful to you for the help.
>
> Regards,
> Marco
>
>
>
NïrzuïïïïïïïrïïïïïzïïyÈïjïïïïïïïrïïï
--
[ signature omitted ]
Here is the code -----Messaggio originale----- Da: Jesse Armand [mailto:mnemonic.fx@xxxxxxxxx] Inviato: sabato 17 novembre 2007 10.53 A: qt-interest@xxxxxxxxxxxxx Oggetto: Re: R: R: R: R: Use of QTcpServer and QTcpSocket between different threads Hmmm, so have you solved your problem yet ? If you don't receive any data (the newConnection() signal is not emitted), then maybe you haven't listen() in a specific socket. Call QTcpServer::listen() before you connect the newConnection() signal. Regards, Jesse On Nov 16, 2007 8:28 PM, Marco Bnà <bna.marco@xxxxxxxxx> wrote: > Exactly... I have a class that have a private member that is a pointer to a QTcpServer that I called tcpServer. > I then do > connect(tcpServer, SIGNAL(newConnection()), this, SLOT(manageNewConnection())); > > to catch inside it the created QTcpSocket, that I save in a private member that is a pointer to the returned socket. > > (e.g. this->socket = this->tcpServer->nextPendingConnection() ); > The purpose is to use the socket to write through it an audio stream that I modify using other methods of the class > But I'm not able the catch the created socket. Data comes to me through a library that gives the possibility to define callback > functions. Defining my own callback func in the main file, I would like to call a method of the class that should give the possibility > to send data through the created socket. > I had (and I'll be grateful to have other) suggestion by Christian but, cause my inexperience in Qt programming I thing, I'm not able to solve the problem. > > Thanks for the help and I'm grateful to you for the help. > > Regards, > Marco > > > NïrzuïïïïïïïrïïïïïzïïyÈïjïïïïïïïrïïï
#include <QtCore/QCoreApplication>
#include <QtCore/QCoreApplication>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <signal.h>
#include <iaxclient.h>
#include "serverwrapper.h"
#define LEVEL_INCREMENT 0.10f
/* static int answered_call; */
static char *output_filename = NULL;
static char *username = "skypetest";
static char *password = "skypetest";
static char *host = "10.15.8.9";
int do_levels = 0;
int intercom = 0;
int initialized = 0;
int reg_id = 0;
ServerWrapper* serverWrapper;
/* routine called at exit to shutdown audio I/O and close nicely.
NOTE: If all this isnt done, the system doesnt not handle this
cleanly and has to be rebooted. What a pile of doo doo!! */
void killem(void)
{
if (initialized)
iaxc_shutdown();
iaxc_stop_audio_socket_in();
if (reg_id){
iaxc_unregister(reg_id);
}
return;
}
void signal_handler(int signum)
{
if ( signum == SIGTERM || signum == SIGINT )
{
killem();
exit(0);
}
}
void fatal_error(char *err) {
killem();
fprintf(stderr, "FATAL ERROR: %s\n", err);
exit(1);
}
void mysleep(void)
{
iaxc_millisleep(10);
}
int state_event_callback(struct iaxc_ev_call_state call){
if((call.state & IAXC_CALL_STATE_RINGING))
{
printf("Receiving Incoming Call Request...\n");
if ( intercom )
{
printf("Intercom mode, answer automatically\n");
return iaxc_select_call(call.callNo);
}
}
return 0;
}
int levels_callback(float input, float output) {
if(do_levels) fprintf(stderr, "IN: %f OUT: %f\n", input, output);
return 0;
}
int netstat_callback(struct iaxc_ev_netstats n) {
static int i;
if(i++%25 == 0)
fprintf(stderr, "RTT\t"
"Rjit\tRlos%%\tRlosC\tRpkts\tRdel\tRdrop\tRooo\t"
"Ljit\tLlos%%\tLlosC\tLpkts\tLdel\tLdrop\tLooo\n"
);
fprintf(stderr, "%d\t"
"%d\t%d\t%d\t%d\t%d\t%d\t%d\t"
"%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
n.rtt,
n.remote.jitter,
n.remote.losspct,
n.remote.losscnt,
n.remote.packets,
n.remote.delay,
n.remote.dropped,
n.remote.ooo,
n.local.jitter,
n.local.losspct,
n.local.losscnt,
n.local.packets,
n.local.delay,
n.local.dropped,
n.local.ooo
);
return 0;
}
int audio_callback(struct iaxc_ev_audio ev)
{
qDebug ("callback calling!!");
serverWrapper->callReadyWrite((char*)(ev.data), ev.size);
return 0;
}
int iaxc_callback(iaxc_event e)
{
switch(e.type) {
case IAXC_EVENT_LEVELS:
return levels_callback(e.ev.levels.input, e.ev.levels.output);
case IAXC_EVENT_NETSTAT:
return netstat_callback(e.ev.netstats);
case IAXC_EVENT_TEXT:
return 0; // don't handle
case IAXC_EVENT_STATE:
return state_event_callback(e.ev.call);
case IAXC_EVENT_AUDIO:
return audio_callback(e.ev.audio);
default:
return 0; // not handled
}
}
void list_devices()
{
struct iaxc_audio_device *devs;
int nDevs, input, output, ring;
int i;
iaxc_audio_devices_get(&devs,&nDevs, &input, &output, &ring);
for(i=0;i<nDevs;i++) {
fprintf(stderr, "DEVICE ID=%d NAME=%s CAPS=%lx\n", devs[i].devID, devs[i].name, devs[i].capabilities);
}
}
void usage()
{
fprintf(stderr, "Usage: testcall [-?] [-v] [-i] [-s SILENCE_THRESHOLD] [-u USERNAME -p PASSWORD -h HOST]\n");
exit(1);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
serverWrapper = new ServerWrapper(0);
serverWrapper->initServer(56000);
FILE *f;
char c;
int i;
char *dest = NULL;
float silence_threshold = -99.0f;
float level;
f = stdout;
for(i=1;i<argc;i++)
{
if(argv[i][0] == '-')
{
switch(tolower(argv[i][1]))
{
case '?':
usage();
break;
case 'v':
do_levels = 1;
break;
case 'i':
intercom = 1;
break;
case 's':
if(i+1 >= argc) usage();
silence_threshold = (float)atof(argv[++i]);
break;
case 'u':
if(i+1 >= argc) usage();
username = argv[++i];
break;
case 'p':
if(i+1 >= argc) usage();
password = argv[++i];
break;
case 'h':
if(i+1 >= argc) usage();
host = argv[++i];
break;
default:
usage();
}
} else {
dest=argv[i];
}
}
dest = "skypetest:skypetest@xxxxxxxxx/4050";
printf("settings: \n");
printf("\tsilence threshold: %f\n", silence_threshold);
printf("\tlevel output: %s\n", do_levels ? "on" : "off");
/* activate the exit handler */
atexit(killem);
/* install signal handler to catch CRTL-Cs */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
iaxc_set_preferred_source_udp_port(4590);
iaxc_set_test_mode(1);
if ( iaxc_initialize(1) ) fatal_error("cannot initialize iaxclient!");
initialized = 1;
iaxc_set_formats(IAXC_FORMAT_ALAW,IAXC_FORMAT_ALAW);
iaxc_set_silence_threshold(silence_threshold);
iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_RAW | IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED);
iaxc_set_event_callback(iaxc_callback);
bool connected = serverWrapper->getConnected();
while (!connected)
{
connected = serverWrapper->getConnected();
}
/*fprintf(f, "\n\
TestCall accept some keyboard input while it's running.\n\
You must hit 'enter' for your keypresses to be recognized,\n\
although you can type more than one key on a line\n\
\n\
q: hangup and exit.\n\
a: answer incoming call\n\
t: terminate call\n\
0-9 * or #: dial those DTMF digits.\n\
g: increase input level\n\
b: decrease input level\n\
h: increase output level\n\
n: decrease output level\n\
Enter: display current audio levels\n");*/
if(dest) {
fprintf(f, "Calling %s\n", dest);
iaxc_call(dest);
}
iaxc_start_processing_thread();
if (username && password && host)
reg_id = iaxc_register(username, password, host);
printf("ready for keyboard input\n");
if(output_filename) {
for(;;)
iaxc_millisleep(10*1000);
}
return a.exec();
}
/*int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}*/
#include "serverwrapper.h"
#include "serverwrapper.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QDataStream>
#include <iostream>
#include <samplerate.h>
ServerWrapper::ServerWrapper(QObject *parent)
: QObject(parent)
{
tcpServer = new QTcpServer();
}
void ServerWrapper::initServer(int port)
{
this->tcpServer->listen(QHostAddress::LocalHost, port);
this->connected = false;
connect(this->tcpServer, SIGNAL(newConnection()), this, SLOT(manageConnection()));
}
/**void ServerWrapper::incomingConnection(int handle)
{
this->socket = new QTcpSocket();
this->socket->setSocketDescriptor(handle);
connect(this, SIGNAL(readyWrite(const char*, int)), this, SIGNAL(writeToSocket(const char*, int)));
connect(this->socket, SIGNAL(disconnected()), this, SLOT(deleteSocket()));
this->connected = true;
}*/
void ServerWrapper::manageConnection()
{
this->socket = this->tcpServer->nextPendingConnection();
connect(this, SIGNAL(readyWrite(const char*, int)), this, SIGNAL(writeToSocket(const char*, int)));
connect(this->socket, SIGNAL(disconnected()), this, SLOT(deleteSocket()));
this->connected = true;
}
bool ServerWrapper::getConnected() const
{
return this->connected;
}
void ServerWrapper::deleteSocket()
{
delete this->socket;
this->connected = false;
}
bool ServerWrapper::callReadyWrite(const char* data, int size)
{
if (!this->socket)
{
emit readyWrite(data, size);
return true;
}
else
{
return false;
}
}
inline short int ServerWrapper::alawdecode(unsigned char alaw)
{
int value;
int segment;
/* Mask value */
alaw ^= 0x55;
/* Extract and scale value */
value = (alaw & 0x0f) << 4;
/* Extract segment number */
segment = (alaw & 0x70) >> 4;
/* Compute value */
switch (segment) {
case 0:
break;
case 1:
value += 0x100;
break;
default:
value += 0x100;
value <<= segment - 1;
}
/* Extract sign */
return (alaw & 0x80) ? value : -value;
}
void ServerWrapper::writeToSocket(const char* data, int size)
{
short* short_data = new short[size];
int i;
for (i=0; i < size; i++)
{
short_data[i] = this->alawdecode((unsigned char)(data[i]));
}
float* float_data_in = new float[size];
float* float_data_out= new float[size];
src_short_to_float_array(short_data, float_data_in, size);
SRC_DATA* src_data;
if ( src_data = (SRC_DATA*)malloc(sizeof(SRC_DATA)))
{
src_data->data_in = float_data_in;
src_data->data_out = float_data_out;
src_data->end_of_input = 1;
src_data->input_frames = size;
src_data->input_frames_used = 1;
src_data->output_frames = 1;
src_data->output_frames_gen = 1;
src_data->src_ratio = 2.0;
}
else
{
std::cerr << "Heap memory is full";
return;
}
int error = src_simple(src_data, SRC_SINC_BEST_QUALITY, 1);
int written;
if (!error)
{
short* short_data_out = new short[size];
src_float_to_short_array(float_data_out, short_data_out, size);
int greater_size = size*sizeof(short);
char* char_data = new char[greater_size];
int char_data_pos = 0;
for (i=0; i < size; i++)
{
short2char* element = (short2char*)malloc(sizeof(short2char));
element->s = short_data_out[i];
int short_dim = sizeof(short);
for (int curr_char = 0; curr_char < short_dim; curr_char++)
{
char_data[char_data_pos] = element->c[curr_char];
char_data_pos++;
}
free(element);
}
QByteArray soundArray(char_data, greater_size);
QDataStream stream(soundArray);
stream.setVersion(QDataStream::Qt_4_0);
written = (int)this->socket->write(soundArray);
delete[] char_data;
delete[] short_data_out;
}
else
{
return;
}
free(src_data);
delete[] float_data_out;
delete[] float_data_in;
delete[] short_data;
/*QByteArray dataBlock(data);
QDataStream stream(dataBlock);
stream.setVersion(QDataStream::Qt_4_0);
int written = this->socket->write(dataBlock);
int written = static_cast<int>(this->socket->write(data, size));*/
if (written <= 0)
{
std::cerr << "ERROR WRITTEN: " << written << std::endl;
}
else
{
std::cout << "WRITTEN OK: " << written << std::endl;
}
}
ServerWrapper::~ServerWrapper()
{
}
#ifndef SERVERWRAPPER_H
#ifndef SERVERWRAPPER_H
#define SERVERWRAPPER_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
class ServerWrapper : public QObject
{
Q_OBJECT
public:
ServerWrapper(QObject *parent);
void initServer(int port);
bool callReadyWrite(const char*, int);
bool getConnected() const;
//void incomingConnection(int);
~ServerWrapper();
private slots:
void writeToSocket(const char*, int);
void manageConnection();
void deleteSocket();
signals:
void readyWrite(const char*, int);
private:
inline short int alawdecode(unsigned char);
private:
QTcpServer* tcpServer;
QTcpSocket* socket;
bool connected;
typedef union {
short s;
char c[2];
} short2char;
};
#endif // SERVERWRAPPER_H
Is there a way to make all the objects part of the same thread?
-----Messaggio originale-----
Da: Marco Bnà [mailto:bna.marco@xxxxxxxxx]
Inviato: lunedì 12 novembre 2007 23.25
A: 'Thiago Macieira'; 'qt-interest@xxxxxxxxxxxxx'
Oggetto: R: R: Use of QTcpServer and QTcpSocket between different threads
In the main there's variable
IaxSocketOut* socketout = null;
The class IaxSocketOut extends QTcpSocket. The class IaxServerOut extends
QTcpServer and implements
Void incomingConnection(int socketDescriptor)
{
This->socketout = new IaxSocketOut(this);
This->socketout->setSocketDescriptor(socketDescriptor);
}
IaxSocketOut* IaxServerOut::getSocketOut()
{ return sockeout}
Socketout = iaxserver.getSocketOut();
So I save the variable. The connection is started when I launch an app which
simulates a client on the port specified and where the server is listening.
The method iaxc_start_processing_thread() called in main func starts a
thread which is involved in chatching events generated (incoming data from
Asterisk). This method as all other with iaxc is part of IAXClient C
library.
Here is the code iaxc_start_processing_thread func
<code>
#if defined(WIN32) || defined(_WIN32_WCE)
#define THREAD HANDLE
#define THREADID unsigned
#define THREADCREATE(func, args, thread, id) \
(thread = (HANDLE)_beginthreadex(NULL, 0, func, (PVOID)args, 0, &id))
#define THREADCREATE_ERROR NULL
#define THREADFUNCDECL(func) unsigned __stdcall func(PVOID args)
#define THREADFUNCRET(r) int r = 0
#define THREADJOIN(t)
static THREAD main_proc_thread;
#ifdef USE_VIDEO
static THREAD video_proc_thread;
#endif
#if defined(WIN32) || defined(_WIN32_WCE)
static THREADID main_proc_thread_id;
#ifdef USE_VIDEO
static THREADID video_proc_thread_id;
#endif
#endif
EXPORT int iaxc_start_processing_thread()
{
main_proc_thread_flag = 0;
if ( THREADCREATE(main_proc_thread_func, NULL, main_proc_thread,
main_proc_thread_id) == THREADCREATE_ERROR)
return -1;
#ifdef USE_VIDEO
video_proc_thread_flag = 0;
if ( THREADCREATE(video_proc_thread_func, NULL, video_proc_thread,
video_proc_thread_id) == THREADCREATE_ERROR)
return -1;
#endif
return 0;
}
</code>
Iaxc_set_callback_func() registers the function I want to use when a new
event is generated...
Iaxc_callback catch events and gets data. I'm interested in audio_data so I
try to take audio event data in audio_callback function.
Here I call the stored variable method process_and_send which contains a
call to "write" method...
I hope that this explanation will help... I'm not able to do an example
because I use the library and I'm new to this kind of programming...
Best regards.
Marco
-----Messaggio originale-----
Da: Thiago Macieira [mailto:thiago.macieira@xxxxxxxxxxxxx]
Inviato: lunedì 12 novembre 2007 22.10
A: qt-interest@xxxxxxxxxxxxx
Oggetto: Re: R: Use of QTcpServer and QTcpSocket between different threads
Marco Bnà wrote:
>I attached the code... Hasn't it arrived?
It did. But we're asking for a *minimal* example.
>-----Messaggio originale-----
>Da: Dimitri [mailto:dimitri@xxxxxxxxxxxxx]
>Inviato: lunedì 12 novembre 2007 21.59
>A: qt-interest@xxxxxxxxxxxxx
>Oggetto: Re: Use of QTcpServer and QTcpSocket between different threads
>
>Hi,
>
>> In my application I have the following message:
>
>It would help if could post a *minimal* example that reproduces the
>problem.
--
[ signature omitted ]