Commit 8413dc1b authored by llea's avatar llea
Browse files

GSM operationnal

parent 745e491e
......@@ -67,6 +67,7 @@ OBJS = \
stun.o udp.o
start: check prereq all
#start: check all
check:
ifeq ($(CONFIGURE_CONF),../configure.conf)
......
......@@ -16,15 +16,28 @@
* License along with dpkg; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "audiocodec.h"
#include "configuration.h"
#include "g711.h"
#include "../gsm/gsm.h"
#include <endian.h>
#include <string.h>
#include <string>
#define swab16(x) \
((unsigned short)( \
(((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
(((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
using namespace std;
static gsm decode_gsmhandle;
static gsm encode_gsmhandle;
AudioCodec::AudioCodec (void) {
// Init array handleCodecs
handleCodecs[0] = matchPayloadCodec(Config::gets("Audio", "Codecs.codec1"));
......@@ -94,7 +107,8 @@ AudioCodec::codecDecode (int pt, short *dst, unsigned char *src, unsigned int si
break;
case PAYLOAD_CODEC_GSM:
gsmDecode(dst, src);
if (gsm_decode(decode_gsmhandle, (gsm_byte*)src, (gsm_signal*)dst) < 0)
printf("AudioCodec: ERROR: gsm_decode\n");
return 320;
break;
......@@ -113,7 +127,7 @@ AudioCodec::codecDecode (int pt, short *dst, unsigned char *src, unsigned int si
}
int
AudioCodec::codecEncode (int pt, unsigned char *dst, short *src, unsigned int size) {
AudioCodec::codecEncode (int pt, unsigned char *dst, short *src, unsigned int size) {
switch (pt) {
case PAYLOAD_CODEC_ULAW:
return G711::ULawEncode (dst, src, size);
......@@ -124,7 +138,40 @@ AudioCodec::codecEncode (int pt, unsigned char *dst, short *src, unsigned int si
break;
case PAYLOAD_CODEC_GSM:
gsmEncode(dst, src);
#if 0
{
gsm_frame gsmdata; // dst
int iii;
bzero (gsmdata, sizeof(gsm_frame));
printf ("Before gsm_encode: ");
for (iii = 0; iii < 33; iii++) {
unsigned char *ptr = gsmdata;
printf ("%02X ", ptr[iii]);
}
gsm_signal sample[160];
for (iii = 0; iii < 160; iii++) {
unsigned short dat;
dat = (unsigned short) src[iii];
//dat = (unsigned short) sample[iii];
//sample[iii] = (short) swab16(dat);
sample[iii] = src[iii];
}
gsm_encode(encode_gsmhandle, sample, gsmdata);
printf ("\nAfter gsm_encode: ");
for (iii = 0; iii < 33; iii++) {
unsigned char *ptr = gsmdata;
printf ("%02X ", ptr[iii]);
dst[iii] = ptr[iii];
}
printf ("\n------\n");
}
#endif
#if 1
gsm_encode(encode_gsmhandle, (gsm_signal*)src, (gsm_byte*)dst);
#endif
return 33;
break;
......@@ -148,26 +195,41 @@ AudioCodec::noSupportedCodec (void) {
}
void
AudioCodec::gsmDecode (short *dst, unsigned char *src) {
gsm gsmhandle;
if (!(gsmhandle = gsm_create() ))
printf("AudioCodec: ERROR: gsm_create\n");
if (gsm_decode(gsmhandle, src, dst) < 0)
printf("AudioCodec: ERROR: gsm_decode\n");
gsm_destroy(gsmhandle);
AudioCodec::gsmCreate (void) {
if (!(decode_gsmhandle = gsm_create() ))
printf("AudioCodec: ERROR: decode_gsm_create\n");
if (!(encode_gsmhandle = gsm_create() ))
printf("AudioCodec: ERROR: encode_gsm_create\n");
}
void
AudioCodec::gsmEncode (unsigned char* dst, short* src) {
gsm gsmhandle;
AudioCodec::gsmDestroy (void) {
gsm_destroy(decode_gsmhandle);
gsm_destroy(encode_gsmhandle);
}
if (!(gsmhandle = gsm_create() ))
printf("AudioCodec: ERROR: gsm_create\n");
gsm_encode(gsmhandle, src, dst);
int
AudioCodec::getSizeByPayload (int pt){
switch (pt) {
case PAYLOAD_CODEC_ULAW:
case PAYLOAD_CODEC_ALAW:
return 320;
break;
case PAYLOAD_CODEC_GSM:
return 320;
break;
case PAYLOAD_CODEC_ILBC:
// TODO
break;
case PAYLOAD_CODEC_SPEEX:
// TODO
break;
gsm_destroy(gsmhandle);
default:
break;
}
return 0;
}
......@@ -20,6 +20,8 @@
#ifndef __CODEC_AUDIO_H__
#define __CODEC_AUDIO_H__
#include "../gsm/gsm.h"
#include <string>
using namespace std;
......@@ -46,18 +48,15 @@ public:
~AudioCodec (void);
int handleCodecs[NB_CODECS];
void noSupportedCodec (void);
static int codecDecode (int, short *, unsigned char *, unsigned int);
static int codecEncode (int, unsigned char *, short *, unsigned int);
int matchPayloadCodec (string);
char * rtpmapPayload (int);
static void gsmDecode (short*, unsigned char*);
static void gsmEncode (unsigned char*, short*);
private:
void noSupportedCodec (void);
static int codecDecode (int, short *, unsigned char *, unsigned int);
static int codecEncode (int, unsigned char *, short *, unsigned int);
static void gsmCreate (void);
static void gsmDestroy (void);
static int getSizeByPayload(int);
};
#endif // __CODEC_AUDIO_H__
......@@ -38,11 +38,12 @@
AudioDriversALSA::AudioDriversALSA(DeviceMode mode) : AudioDrivers () {
audio_hdl = (snd_pcm_t *) NULL;
initDevice(mode);
}
AudioDriversALSA::~AudioDriversALSA (void) {
/* Close the audio handle */
snd_pcm_close (audio_hdl);
if (audio_hdl != NULL) snd_pcm_close (audio_hdl);
}
......@@ -56,16 +57,16 @@ AudioDriversALSA::initDevice (DeviceMode mode) {
}
// Open the audio device
// Flags : blocking (else have to OR omode with SND_PCM_OPEN_NONBLOCK).
// Flags : blocking (else have to OR omode with SND_PCM_NONBLOCK).
switch (mode) {
case ReadOnly:
/* Only read sound from the device */
err = snd_pcm_open (&audio_hdl, ALSA_DEVICE,SND_PCM_STREAM_CAPTURE, 0);
err = snd_pcm_open (&audio_hdl, ALSA_DEVICE,SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
break;
case WriteOnly:
/* Only write sound to the device */
err = snd_pcm_open (&audio_hdl, ALSA_DEVICE,SND_PCM_STREAM_PLAYBACK,0);
err = snd_pcm_open (&audio_hdl, ALSA_DEVICE,SND_PCM_STREAM_PLAYBACK,SND_PCM_NONBLOCK);
break;
default:
break;
......@@ -81,6 +82,7 @@ AudioDriversALSA::initDevice (DeviceMode mode) {
////////////////////////////////////////////////////////////////////////////
// Allocate space for device configuration
snd_pcm_hw_params_t *hw_params;
err = snd_pcm_hw_params_malloc (&hw_params);
if (err < 0) {
printf ("Cannot allocate hardware parameter structure (%s)\n",
......@@ -88,6 +90,7 @@ AudioDriversALSA::initDevice (DeviceMode mode) {
return -1;
}
// Init hwparams with full configuration space
if ((err = snd_pcm_hw_params_any (audio_hdl, hw_params)) < 0) {
printf ("Cannot initialize hardware parameter structure (%s)\n",
snd_strerror (err));
......@@ -106,22 +109,29 @@ AudioDriversALSA::initDevice (DeviceMode mode) {
if (err < 0) {
printf ("Cannot set sample format (%s)\n", snd_strerror (err));
return -1;
}
}
unsigned int rate = SAMPLING_RATE;
unsigned int exact_rate;
exact_rate = rate;
// Set sampling rate (8kHz)
err = snd_pcm_hw_params_set_rate_near (audio_hdl, hw_params,
&rate, 0);
&exact_rate, 0);
if (err < 0) {
printf ("Cannot set sample rate (%s)\n", snd_strerror (err));
return -1;
}
if (exact_rate != rate) {
fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n ==> Using %d Hz instead.\n", rate, exact_rate);
}
// Set number of channels - Mono(1) or Stereo(2)
err = snd_pcm_hw_params_set_channels (audio_hdl, hw_params, MONO);
if (err < 0) {
printf ("Cannot set channel count (%s)\n", snd_strerror (err));
return -1;
}
}
// Apply previously setup parameters
err = snd_pcm_hw_params (audio_hdl, hw_params);
......@@ -129,40 +139,13 @@ AudioDriversALSA::initDevice (DeviceMode mode) {
printf ("Cannot set parameters (%s)\n", snd_strerror (err));
return -1;
}
// Free temp variable used for configuration.
snd_pcm_hw_params_free (hw_params);
////////////////////////////////////////////////////////////////////////////
// END DEVICE SETUP
////////////////////////////////////////////////////////////////////////////
#if 0
// keep fragsize less than 20ms !!
int frag = ( ( 32767 << 16 ) | 7 );
if( ioctl( audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag ) ) {
lasterror = QString( "SETFRAG" ) + QString( strerror( errno ) );
printf( "ERROR: %s\n", lasterror.ascii() );
return -1;
}
audio_buf_info info;
if( mode == WriteOnly ) {
if( ioctl( audio_fd, SNDCTL_DSP_GETOSPACE, &info ) == -1 ) {
lasterror = QString( "GETISPACE" ) + QString( strerror( errno ) );
printf( "ERROR: %s\n", lasterror.ascii() );
return -1;
}
} else {
if( ioctl( audio_fd, SNDCTL_DSP_GETISPACE, &info ) == -1 ) {
lasterror = QString( "GETOSPACE" ) + QString( strerror( errno ) );
printf( "ERROR: %s\n", lasterror.ascii() );
return -1;
}
}
audio_buf.resize( info.fragsize * sizeof( short ) );
#endif
// Success
devstate = DeviceOpened;
return 0;
......@@ -174,10 +157,11 @@ AudioDriversALSA::writeBuffer (void) {
printf ("ALSA: writeBuffer(): Device Not Open\n");
return -1;
}
#if 1
int rc;
size_t count = audio_buf.getSize();
short *buf = (short*)audio_buf.getData();
size_t count = audio_buf.getSize()/2;
short* buf = (short *)audio_buf.getData();
while (count > 0) {
rc = snd_pcm_writei(audio_hdl, buf, count);
if (rc == -EPIPE) {
......@@ -188,10 +172,12 @@ AudioDriversALSA::writeBuffer (void) {
printf ("ALSA: write(): %s\n", strerror(errno));
break;
}
printf("rc = %d\n",rc);
buf += rc;
count -= rc;
}
}
return rc;
#endif
}
unsigned int
......@@ -225,7 +211,7 @@ AudioDriversALSA::readableBytes (void) {
int
AudioDriversALSA::readBuffer (int bytes) {
if (devstate != DeviceOpened) {
/* if (devstate != DeviceOpened) {
printf ("Device Not Open\n");
return false;
}
......@@ -238,7 +224,7 @@ AudioDriversALSA::readBuffer (int bytes) {
size_t rc = read (audio_fd, buf, count);
if (rc != count) {
printf ("warning: asked microphone for %d got %d\n", count, rc);
}
}*/
return true;
}
......@@ -249,23 +235,33 @@ AudioDriversALSA::readBuffer (void *ptr, int bytes) {
return -1;
}
ssize_t count = bytes;
#if 1
ssize_t count = bytes/2;
ssize_t rc;
rc = snd_pcm_readi(audio_hdl, ptr, count);
if (rc < 0) {
return -1;
} else if (rc != count) {
printf("warning: asked microphone for %d frames but got %d\n",
do {
rc = snd_pcm_readi(audio_hdl, (short*)ptr, count);
} while (rc == -EAGAIN);
if (rc == -EBADFD) printf ("Read: PCM is not in the right state\n");
if (rc == -ESTRPIPE) printf ("Read: a suspend event occurred\n");
if (rc == -EPIPE) {
printf ("Read: -EPIPE %d\n", rc);
snd_pcm_prepare(audio_hdl);
}
if (rc > 0 && rc != count) {
printf("Read: warning: asked microphone for %d frames but got %d\n",
count, rc);
return -1;
}
return rc;
#endif
}
int
AudioDriversALSA::resetDevice (void) {
printf ("ALSA: Resetting device.\n");
/* printf ("ALSA: Resetting device.\n");
snd_pcm_drop(audio_hdl);
snd_pcm_drain(audio_hdl);*/
return 0;
}
......
......@@ -50,9 +50,10 @@ public:
unsigned int readableBytes(void);
int audio_fd;
snd_pcm_t *audio_hdl;
private:
snd_pcm_t *audio_hdl;
};
#endif // _AUDIO_DRIVERS_ALSA_H_
......@@ -114,8 +114,9 @@ AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioDrivers *driver,
this->sym =sym;
this->audioDevice = driver;
#ifdef ALSA
if (manager->useAlsa)
if (manager->useAlsa) {
this->audioDeviceRead = read_driver;
}
#endif
// TODO: Change bind address according to user settings.
......@@ -129,10 +130,13 @@ AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioDrivers *driver,
qDebug("Forced port %d", forcedPort);
session = new SymmetricRTPSession (local_ip, forcedPort);
}
AudioCodec::gsmCreate();
}
AudioRtpRTX::~AudioRtpRTX () {
this->terminate();
AudioCodec::gsmDestroy();
if (!sym) {
if (sessionRecv != NULL) {
delete sessionRecv;
......@@ -152,7 +156,7 @@ AudioRtpRTX::~AudioRtpRTX () {
void
AudioRtpRTX::run (void) {
AudioCodec ac;
// AudioCodec ac;
unsigned char *data_to_send;
short *data_mute;
short *data_from_mic;
......@@ -163,7 +167,6 @@ AudioRtpRTX::run (void) {
int expandedSize;
short *data_for_speakers = NULL;
int countTime = 0;
data_for_speakers = new short[2048];
data_from_mic = new short[1024];
data_from_mic_tmp = new short[1024];
......@@ -259,33 +262,35 @@ AudioRtpRTX::run (void) {
////////////////////////////
// Send session
////////////////////////////
//int size = AudioCodec::getSizeByPayload(ca->payload);
int size = 320;
if (!manager->mute) {
#ifdef ALSA
if (manager->useAlsa) {
i = audioDeviceRead->readBuffer (data_from_mic, 320);
i = audioDeviceRead->readBuffer (data_from_mic, size);
}
#endif
if (!manager->useAlsa) {
i = audioDevice->readBuffer (data_from_mic, 320);
i = audioDevice->readBuffer (data_from_mic, size);
}
} else {
// When IP-phone user click on mute button, we read buffer of a
// temp buffer to avoid delay in sound.
#ifdef ALSA
if (manager->useAlsa)
i = audioDeviceRead->readBuffer (data_mute, 320);
i = audioDeviceRead->readBuffer (data_mute, size);
#endif
if (!manager->useAlsa)
i = audioDevice->readBuffer (data_mute, 320);
i = audioDevice->readBuffer (data_mute, size);
}
//qDebug("read i = %d", i);
// TODO : return an error because no sound
if (i < 0) {
break;
}
for (int j = 0; j < i; j++)
data_from_mic_tmp[j] = data_from_mic[j]*manager->getMicVolume()/100;
// Encode acquired audio sample
compSize = AudioCodec::codecEncode (
ca->payload,
......@@ -298,7 +303,8 @@ AudioRtpRTX::run (void) {
} else {
session->putData(timestamp, data_to_send, compSize);
}
timestamp += compSize;
//timestamp += compSize;
timestamp += 160;
////////////////////////////
// Recv session
......@@ -320,7 +326,7 @@ AudioRtpRTX::run (void) {
data_for_speakers,
(unsigned char*) adu->getData(),
adu->getSize());
// Set decoded data to sound device
audioDevice->audio_buf.resize(expandedSize);
audioDevice->audio_buf.setData (data_for_speakers,
......@@ -329,7 +335,7 @@ AudioRtpRTX::run (void) {
// Notify (with a bip) an incoming call when there is already call
countTime += TimerPort::getElapsed();
if (manager->sip->getNumberPendingCalls() != 1) {
if ((countTime % 4000) <= 10 and (countTime % 4000) >= 0) {
if ((countTime % 3000) <= 10 and (countTime % 3000) >= 0) {
manager->notificationIncomingCall();
}
}
......
......@@ -919,7 +919,7 @@
<x>20</x>
<y>21</y>
<width>150</width>
<height>20</height>
<height>30</height>
</rect>
</property>
</widget>
......@@ -1189,16 +1189,18 @@
</property>
<property name="geometry">
<rect>
<x>25</x>
<y>46</y>
<x>20</x>
<y>170</y>
<width>371</width>
<height>121</height>
</rect>
</property>
<property name="text">
<string>&lt;p align="center"&gt;Copyright (C) 2004 Savoir-faire Linux inc.&lt;br&gt;&lt;br&gt;
SFLPhone is released under the General Public License.&lt;br&gt;
For more information, see http://www.sflphone.org/&lt;br&gt;
<string>&lt;p align="center"&gt;
Copyright (C) 2004 Savoir-faire Linux inc.&lt;br&gt;&lt;br&gt;
Laurielle LEA &amp;lt;laurielle.lea@savoirfairelinux.com&amp;gt;&lt;br&gt;&lt;br&gt;
SFLPhone-0.3 is released under the General Public License.&lt;br&gt;
For more information, see http://www.sflphone.org&lt;br&gt;
&lt;/p&gt;</string>
</property>
</widget>
......@@ -1210,6 +1212,24 @@ For more information, see http://www.sflphone.org/&lt;br&gt;
<attribute name="title">
<string>About Savoir-faire Linux inc.</string>
</attribute>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="geometry">
<rect>
<x>85</x>
<y>126</y>
<width>291</width>
<height>131</height>
</rect>
</property>
<property name="text">
<string>&lt;p align="center"&gt;Website: http://www.savoirfairelinux.com&lt;br&gt;&lt;br&gt;
5505, Saint-Laurent - bureau 2027&lt;br&gt;
Montreal, Quebec H2T 1S6&lt;/p&gt;</string>
</property>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>pixmapLabel2</cstring>
......@@ -1229,24 +1249,6 @@ For more information, see http://www.sflphone.org/&lt;br&gt;
<bool>true</bool>
</property>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="geometry">
<rect>
<x>85</x>
<y>126</y>
<width>291</width>
<height>131</height>
</rect>
</property>
<property name="text">
<string>&lt;p align="center"&gt;Website: http://www.savoirfairelinux.com&lt;br&gt;&lt;br&gt;
5505, Saint-Laurent - bureau 2027&lt;br&gt;
Montreal, Quebec H2T 1S6&lt;/p&gt;</string>
</property>
</widget>
</widget>
</widget>
</vbox>
......@@ -1255,7 +1257,7 @@ Montreal, Quebec H2T 1S6&lt;/p&gt;</string>
</widget>
<images>
<image name="image0">
<data format="PNG" length="3612">89504e470d0a1a0a0000000d49484452000000ad0000003008060000006357fade00000de349444154789ced5d5f685bd71dfe69a4e00e3394b28724946197b5600fcaaee73ec85d4baee94b65a7a4525b68bcf5418a33626f7ba8ddbee4cf48d5305247850cabc39d951266b760ec3c24b2076656868b5c48667978c88114ece10db998a21863142302df1eaeeed5fd73cebde75e29a9d3e8bc7c96ef3de7fcced1ef7ce73bbf7bce1581884689a8660800eb000064ca881250f37aeaf8d862d50e9aba930700482373a0f3009d9be4a23c0e0ccce60000df75c3ebf8e8a2a78cb94d8540fdf114681da0f393aed1bf0944aea1eec075748dee320090af3833aa5b94c781fc76b12e21ea28844237a2a430a217467583b1f95cdd71ebe8888e37e4368b9092b565563b9446e6ea92a18eb6687b033601ffe683675833fae3a9bae3d6918bdc0bb9cd22fc710f8c99488192008dcc819240f0ea220060724589328896e3bf3059bde302181e1945e4641f22bd7d658c2072b20f43f12100403e9f7f74240980d4b5da0ee8e27611437120d2db87c0611991de88f7f21f807d2cac0dc35e500cc5366c5366150f85715104b00ab4b44b28b417d1d22e416a0f703f9f3a177b2498fdd4b998667fcdec5d80a53f06de1bf034901f887d0cb48ebc125c33ac488acc2c7ad2b85e183772b2cff04504bb43181e1905008c8d4f027140ee0e6ad7a5f60016b38b7b9f7155fb6be510303aacd41e40a4b7af2aa6ada97d1cb4fc43864b0deac0ae001098c854a571e52b197187829161b1ccef40dc51ec4bcda46ccb57efabd641aaba6e675fde837d00028765cb0c8482437f3d04fb9ceef78d1251948892441405e0fb608a685f98e8be1846a42c255f6d235e8afe2d4b9797da84cbe3e1d8910dea79fe902fa9b79781d9ec228e9ff82dedd22e35500305e40e4a0cc51df3191040f8580fad7dbda695a3c7a01ca4fede28353ff78cafe3b08cdd9d5d6a686ca0851b694afa7c3e7d79e9f90c4e9f3d4d5b3b5b24b5b450e75f3ff7a976b67dd1461db73a697767d750bed4d242d2cf251a7c77d0585e1c68fda28d1aa8812e7e7c913a5f7ed197181945f22f492dbfffc07edafae62eedd22eaddcca5aec5151b59bd53e2d1f80ce235d5a79fafb1a1a1b68414ed346ef061d3c54fe5e04ec6b686cd0daabaf27f1699266aecfd0da376b867afc07f653faf569baf7e63d7af2473ff425c934f2bc3ce1b24b6e35acd31334a13d0cb06ab4607708280099f98cd08857f3070ecb4a43ca4c3bf0de80c648815764a008e0954a7dc1eea0d5bea3d6eb43f161ab7d0b40e4649fa13cb336343062a9fc7f8626553f9f3a17e3f717d89a1fcb50daa5ab2fd81d0200454295fb41bbff6895f699181f47a1fcbf0084de3e66ecef32d36b4c1bbdb688cbfff6c0883f4e134e743259b69f883e71c9dc76183b1ba6831ce6303365eb0b6d16063133454b4b0b75feb2937a8e858d8c0420bb94a5b6b65f5818bab55d829e91129f2649cf24d3d7a62acc63b263e55696a6af4fd3990fced32eed92bfd14ffdbdfdd4d3f386cfce7e959112ed01a8f5447ba3d4ff9be3be686f1f9696962c4c7deccd63d4f55ab76f7c7c123dff0a53742b4ab4af81da7ede46fd27a21ac3e9eb091d0951f31fce38f743adec3bd245d113fda45e0fca416a193a6ff87e4f9f8b61e6fa0cedd22e055e0850c79f3ff1291aa2545d3c56dd8b60499bb5635ad7d1040043f16160562c8aa03103a33c956182dd21437e64a13185856148594d5b18e968c59eb189493e13ae56184a5dcd33ed5d306978533b58ed55eb4516d6f6d8f4abdade6077d0509eba88756b1fee18eb0fbd7dccc0e89887e5fb030085693d68593d06ce866981c9b54417bf5aa3f76e34d78469156dbb463dcf3fe34ea312d1463e8f83070f52facb05eafcba83c27fb76a56bdc6ea7f7f90966e65696b678bcbd8eafd77e3c0e5b29653b5eddad76bd47322aae58f9d3d455daf75fbcc4ccdd39ce9f90c06df1dd41839fa8f1b1c268b6069e9b66657ff3fbfb230d5c6371b44f789681f5143e39394f8e82293692df6b8ec07d7f609cc887af437fa69eedab4e2f1d248f58c689786166ac7b8051b46748ba999948131464746a167384dd39657b36313934c86411e5c06d73461b95e567e27cda9e617d18c6edabf985d64b6c7cc90aaa6d5f7038ba1ddda67ae5f345efe838ded2296be25a2cfa68828ec19a76e6f70b89668304034b9b3a1306695f53cf5c7298a0270d2b4d9ec229ceeeb7ab58b5ea417b5917c77274aad6f191933e9f3f9e890cf97f4f97c3d6fbde10b1f7843bbbf4d6aa32411d1219f2f7824480dd460284ffd3cfdfa9456efa034a85dfffc8babdc99217caca792ff0525bfbefcc46749652df259bfa13e3733509bd466b0576d4f1440ebef957ee86aeca2e9eb53c67e78336c681f49e4c93e73fd1f9e3dcd9d7936f279a89f09a8010326e66c99564be5986eb5f58d2ddb682f58e3b46313e599a0a840663e636054557362de46e3c1b86a665d6769662dca60639f21fe09c6aa395f613247cd68c3502c8dca6a8f7e060abc221b19d8649f6b4d6bb6a350b9aece6c9a7d4500a5ca9a418b1e44bc460d54f44f13fabab82ccb4bbe4fd344df767aaa77e06c985a3823f2de7611c7fb8fd3d2eddbc25a496a69a10fcf7c48cdcf3693393eeb3fb09f7677ee31359d45039e035aaf1b359aaaedcc33012ffea9c7e603cd34fcf1456a7e4ed1f0c9c332543b589ab1f940338552579da32bc4d6947a4ddf211be3c722fd70b53b0435cecab24fd5e6663bf46b025e7f343fdb4c539f8f2b8c5f0df385ca9b61bca653e99cc72764364cab6384a1f810787142cc82ada1506666356ebaa0302c505ed596a0685f95b9f5cc55def3a0e61b8a0fd9da999a4919eeafe41bb6daa5deafb347b557cd979977f1e450d75eb53dccffebec52fb0b5918fa41d43edb278f8cfa2227fb8055285104ddfde469dfeba5caaead6a5366b5004ab8abdf1fdffb9b5beaf8e0903c450904f61bb84adb65d27263874dc3d4931603b3808cca61cafaa9e0ef078a33ed05b1dd5cd526517bec1ad6c4616e29593d4317cb0322b35e00c0294f773db35ea8e9402972069e5a5f6c3e8718caa7a46b50dff0cd554450deb40420b7696c4fea4e1ef2b8725dc139c4e0fdcc5f6eb380188ce5854ce589316de2a1f8ab96aa655aaff944b050b2ce3c6687e5cd505539102a7b43a41118b5f43698edcdaca3aaf60edfb496ebdf146b2fad97673817ed0bd9ec06d4f79f33d33e248635a76a98d66b3ea1a9c9549ef930666822c3b55b1e07784c29c278dc7670fa2b86eada1be394ab77a0620990c7f9fd2d74e60f40d3a514b7dfccf91d99f641a4dca6a261532b0e8ebb0799d689419df6234ba5f25e0db7f583df8ecc3a9b6963f31eead1616cde058383bf4bd076cf884dbea6043b1fd97978a0f6fe5a7148dd99b2210005c6e22e04b65d4edaf4bb645a91f742f8e3eeb56e6c3ee79a69b98ee266a0b82917f66f1a6a4a5434f7c06c0ebcb5079db77f13115f936c821b25085d05a8a448075a07e88a07a7dd66d45b16fb5ada06a860bd2f34813dcbb4dcfe74fb648fe5409c7680cbb4d5bd472236cf8ea3c3412bf3185a04fd9bcee55b46b08a41d3838381740e74893ff25c3b2d6f449a3474e8aaf56c99c551cc8ef59d322d5fd3b230724dec6c9a17a67d189a968799f582ebb38652524cf3dbae7635074bccd98e10276dca74da12bf3c4bfd2e57c57b49d34a2520a53f6306c5d1f5fb97431302272ac06fc79ed0b40c7473aabb691bc271742e33551c96af791f08d39a34b5f93eff0567c7db4b9a96c71cc59251b33badb207661f014d2b989f854d97c437f813882834611d5100402267c63c3e1d73625a9178dd5e645aa0725de81431ace5615be7e80058f15203a3ed314dabdaedf6cca1e82bb1aa3fb9f0f402e19d0e729bbceef2cafcfa2e75fce429db930bc7cf03bcfcf9dfdda383e5539d6e4e3ea8e83b37097d79b19756e8f4cb3fd3caebbc92c18dff7510dd9f22f9a761eae9113bd3b6ffa329daba2fde0fa3a78c270c58df9ff0993a0ede061067948bb361eebed77b25e0c92788bcfa937fdf14dd7d9f5fbee1346e136b352fc87c0f8b6985767711d933adc048ae95a615b5d70b33e9f3e73867f15cd5cfc0a604db1eae865d07ecfc481a51befbd8bc12cee295cf9c71f4dfaffac7d8725e487b384519849dd6653d6eb49453391138ec1db01b102e34ad3ceefe051a226f546769735ebcddab44885c63bf118819ed801257b58b0af0e2d2c33757b951067f1c18beb96ac947c60ef7f0269892078ff5f03e04d98583799931ec467c4a77b2a0e69a96e930cefde386a965358eeeb03a5777c7f11890a9396dee179dd9b00d483633af6abf51d392f737cca81ac74d72fb3e047f6398567ac5b5a89da6f58aaa8674d2b4faf747086b5a068e2fafe257d7f9a7980d9a56f7fd35ff699afeb3d3c5cd273fbd40fbdfe920e9cb15a2975a89be5ca1f47f5b696b274d4b366b0cf9e934a5dfe9d4b4e6bd1270e6092296e615d5a6665c007059a03cc7d5ac089e4ae75c11ad50544287ae9e1c51393c5423a635afc2cd71583ba61d987567374b23b218481a99b32d776c1930ef46ab66a6e1ed35e033a340dc99873633866a0f3363042e35e705e504824872fbf644d127466634ef7bf58abc8e75ba5ed3df9030dbe522dfd8f2aa617f2a4ffb4a237390c795071dda7e5c1bc71b5b56f6d1fa2f28f9e52b198450a37dbc50b4ac3c5ef98d8fa64b29edb739b8dac64e6330715b7977975d72fbfe03af9ab08edf6fb4652a2fbfb5c03bec288dbb7b262ff468b38e8f253adf88da694351f42a09eaf878a0d88da868172ff15551f4c7150db6173aa68e7b17c53394c5fc83625819e03e01a9631df5e83a4366bd607b26c82d56151ea9e36389de0b801287f4b267413dfb5367d63a7ac1da1404606c5989eb8526329673f021543649d47f03b78ed5e2ff01a9e39f669eee93e00000000049454e44ae426082</data>
<data format="PNG" length="3470">89504e470d0a1a0a0000000d49484452000000ad0000003008060000006357fade00000d5549444154789ced5d5f685bd71dfe0952708619cad8431ccab0cb5a7006a5f2dc07796bc9357d99e294546e1f626f7d90e28cd8db4b9df6c5498aabe6c17554c86675b8b30261560bc6ce83a378106665a8c885649687871c48c11ede908b198e31c61626f0ede1fed1fd77ee3de74a4e9d46e7e54b7ccf9fdf39f777befb9ddf3de78a4044634454350480550000720a620fa87a3b357c66b162074d3f2c020002a3b3a02b000d4e32514a01fd770a0080efbae3357c7ad153c1c2ba4ca0fe781a0480ae4c0aa31f40641a3507aea1308a150020dd70675451945240716ba726216ac8855c19b12733a2174615c158b65073dc1abaa26b86c2fa0e02c9ea32ab130646676b92a1868ee89801eb80ff0930ac19fdf174cd716bc844e685c2fa0efc710f8c99488392008dce829240e8e63c006072498e32f0d6e31f9aacdc71018c8c8e2172be17919e5e0523889cefc5707c1800502c169f1e4902203d5ddd09bdb3b583e13810e9e945f08484484fc47bfdfb609f1d568761876443b105c7945bc613615cec00d8039a5b0340ab8c81d620f3ff0383b1a782d90706639afd55b377d53a1efdeff77b9ac8fb629f0d5a67de1e841996274566e63d695c2f8c1b39df6bb811a18e304646c70000e3a949200e481d21ed7aa03588f9fcfcc1675cd5fe6a39048c0e1b680d22d2d35b11d356d53e065afe208930ac826e293891ab48e34a3772fc0e0523c362833d807828db979e493bd6afe6abd4412abaee645fd1837d00822724cb13c8a91e3c84a7892d6a9f5b7edf181145892849445100be8fa6880e75123de6c348204fc95fb5102b45ff9aa7eb0b2ddcf5b170fcd41a75bf7ccc97d4db6b83f9fc3cce9efb1d95a84475544741a98d12c371d7720604d0d9d54d2bdfac68f5e8312485a8af274a4d2fbde06b3b21a1b45da2bafa3a9abb9ba1a4cfe7d3d797c9e670f1f245dadcdea4407333b5ffe50b9f6a67cb972dd476bf9d4adb2543fd81e6660abc12a00bef5d30d617078e7fd942755447573fbd4aedafffc297181d43f2cf49adbcffe811dafcf61195a8444bf7f3167b5454edb6eb9f560e40fba9935a7dfa7c75f57534276568ad678d1a8e29f785c3bebafa3aadbffa76129f2769e6d60cad7cbb6268c77ff40865deba4dbbefecd2e11ffec09724d3ccf3f286cb29896a58b737685c7b1860d568a18eb06c4f36c735e3d5f2c11392dc118569fbdfefd71829f88604ec0078a3dc5ea82364b5efb4f5fa707cc46adf2a1039df6ba8cfcc7cb68c68a349d5ff0f0cc6d8e30586e6df80dc2f5d7beaf8cde7e7b571d0f29faed03e33e39f2eaf31c267ba8ce3ad30bdc6b4d1e9795cff970746fc718670aedd9665fb88e83341e676c2d8e54e6a60308799298fbfda626110335334373753fb2fdba9bbabd3c84800f20b796a69f9b985a18fb706a067a4c4e749d233c9ede9a932f398ec58ba9fa7dbb76ed3a58fae50894ae4aff7535f4f1f7577bfed73b25f65a4446b106a3bd19e28f5fdf6ac2fdad38b8585050b5377bdd34527dfecf0a55293e8fe67274537a34487eaa8e59516ea3b17d5184edf4ef854989a3ebce43e0ed5b2efd4498a9eeb23f57a480a51f3f015c3fdbd3818c3ccad192a518982af06a9ed4f9ff9640db157593c56dd8b6049ebd5635ae1680280e1f808b0c4194570a85765985047d8501e79684c61a70907066356463a5db6677c6292cd847b65fbd4d5bcadbdab260d6fea875d7fd5769187b53f0ee3aaf637d41132d4a72e6245edc34363fbe1335d0646471696fb070032d3425ccbea3178b993e66cb996e8ead72bf4fedda6aa30adac6d57a8fbe517c4342a11ad158b686868a0cc5773d4fe4d1b75fecdaa59f51aabef830bb4703f4f9bdb9b4cc656f33f8a03d7152da76adb956f56a8fb5c542b1fbb3c4027dfecf099999aa53933d91c2ebc774163e4e8dfef32982c828585079a5d7dfff8dac2546bdfae113d26a2434475f58729f1c9555ba6b5d823380ec2f6713c11f5e8aff7d3ecf46dd9e303a39533a2531a9eab1ee372332d07a667d206c6181b1d839ee1344dabac66c727266d190645b0195cd5846abb36e5dd34a75a9e4b330af47f3e3f6fdb1f3343aa9a563f0e760c2d6a9fb97dde78b9afb8b583637f3c5c31034ebeb5469dcd0d0cbe259a7ab0466fdf6a202a55ceb8b8dcc9642883160bb4b8e6d3cff4c8993c9919d35cbebd2304bbd5b95e7b5998e87c9e9251399f5ee3d96938153bcf74417d122c9dca53f2433ecd68665a11edaf7fd2a87fb71d07463961fbdc989e4c4f4a65ad40a8060326661d99564bca1bb34adb1b5f04f7aa181b0a4302f2aa184a1461cfc400a701641d341e4cab669beb769a598b3238d867887fc266d55c2c3399ab6614605a96a6d53f81826f48460636d927ac691dee97fa64d3ec53ee97ba66d0a20711af510315fdb709bd27990ccb4abecf3344ff6bf7d46effe54e6a66ccc8ddad1d9ced3b4b0b0f1e706ba54073337d7ce9636a7ab189ccf159ffd12354dadeb5d574166618048edf326a349571cc0cc78a7feab1e968138d7c7a959a5e92357cf28404d50e3bcdd874b489c2e99b5561da36c9183fe619879b1d61a871563bfb546d6eb643bf26608d47d38b4d34f5458a923e9faf22a60d2b9b61bca6814cc1e31b3207a6d5cde0e1f8305871422c31f61c406166356ebaaac467515ed58e29af840d0caa32c35eb9dc707cd8d1cef44cda90bf5c6ec46a979a5f678f6aaf5a2e97157873a8ebafda1fdbbfebec52c74b8d2298cbb9d9e7f8e6d1a6bdc8f95e39369f358e3379daf77aadbc6babd2945bde0025c4daf7c70ffee6961aee1f92a72881cb6e2ee1e441eb3a6a35e5a445ff1d4042f93065ed54f0f703f99976886f3757a589d71ea78e3532983b90ac9ca1779409915bdd00c0a84f773db7ba51d589b2c398786a7bb16c013128a7a4abd0dec8bd6544a06c5a02505837f627fdb00829255f97711631783ff35758df400cc6fac2a6faf89836f144fc554b9532add7725c68ae0f562db82ff16594f786044661d4d25bb0ed6f6e1515f577e49eb55e3f677f09ca134ea07f6187dd80faf17367da27c4b0e65409d37a2dc7f56832d5673e8c199ec831ed9652008b2979188fd90fc678c550597f638c7af50eb4b3074829f678739df903d0782dcd1c37737957a6dd8fa4ee55482f39e73b884cebc6a06efb91036aff45db77e8476ed59e6963590fede83096156070b077093aee197128d798b02f474e1e1ef4e6935c497fa66c18c086cde22e0c7bbbdcb4e977c9b43cdf85f0c7c5b56e2c5b10665aa6a3884c14917ae1fca5a1c6445973f7df2980b5f6a02bce5f2272d424ac2841f8a632038794fc373c38ad5dbb8ad8d71243ab8527706099d6693c85deecd93910a31f60326d65df918865ede3e870d1ca2c86e6413f47fd9619ac62c8f4e2a03f53005d63cf3c61a765cd4893860edfb49e2db3388ad9b1be53a6656b5a3b8c4cf39d4df3c2b44f42d3b230b7ba217cd63090e4d3fc8eab5dcdc112b38e33c44d9bda3aad437d96f60557c50749d30600a4f567cc203bba7eff727882e34485433f0e84a6b5419153dd8d00771c9dc94c6587656bde7d615a93a636e7f30fb93bde41d2b42ce6d8d9336a76b75576ff9da740d37296b7c3c66bfc1bfc0944149eb0ce280020ce33639e9c96a35eaff1ce83a269b94e11dbd4872d9da303b08b971a18ed80695ad56ed13387bc9fc4aafce4c2f3738477db483479dde595fbcd236afbc98f1c4f2e9cbd02b0ca177fbf4b0dcaa94e91930f2afa0627a1af2ff6da125d7cfd675a7ded3772b8fbdf36a2c75324fdb493babbf9ceb41df9648a361ff38fc3d880717fabddfde33e53c7c00700e236f53aed67dedd030e3f47e4d59ffc87a6e8d107cefba5350f6eac80f99e14d372edee2272665a8e995c2d4dcb6baf1766d2972f30cee209b56f838d097b7b981a761570f2a3c0a87cef6359399cc5aadff689a3bfbfea3fc6178b5cdac32dcac0edb482ed886829b77a2270d93be034210434ad9412ff8006cf17d5edb4392bdeee552244a6edbf08641bed801c57758a0ab0e2d223f7969951067f1c18b9b76c2947c601f7f62518e1e4e17b0892808379796238cdf8b4ee6441d535adadc3b88f8f08534b6a1cdd6575aeee8e6331a0ade674c8cffb64c3161070e8af6abf51d392f72fcca81a4724897e0fc15fdf494b3dfc5ad449d37a455543ba695afdf723b835ad0da61697f1eb5bec53cc064dabbb7f4d7fb84dffde3ec92c273d3f4747de6da3c0574b44af1d27fa6a8932ff394e9bdb195a70586348cf6728f36ebba63577f7804bcf11d9695e5e6d6ac63900d739ea735dcdf2e040a62044b4bc51091585de1c91121eaa12d39a57e1e638ac13d3f6df11b3db4e23da31506074d6b1def145659cabf4a461ed3560332347dc998570d6f600605b300241cd39249f40e049a25f4fe47d636446f3be57afc81a58b7eb55fd0d09b35d02e5c617970dfb5359da37303a0b2925bfe8d0f6e33a38def8a2bc8fd63f2497976ee4104695f6f142d6b252aafc1b1f8dd7d2da6f7330b58d93c660616ed9d96145bf7fe05513d6f0fb8d8e4ce5e5b71658871d0329b177f25caf366bf84ca27b460f8c5b297a9504357c36902f23cadac54b7c9517fd7159831d8481a9e1c145fe028ac6dc2f869500e61b901ad6508fc20572ab1b8e678244b1a2f0480d9f49f45e01e43864a3076655cffed498b5865eb03a1501185f94e37ae1899ce51c7c18e54d12b5dfc0ad61a5f87f436b14a98cd921cb0000000049454e44ae426082</data>
</image>
</images>
<connections>
......
This diff is collapsed.
/****************************************************************************
** Form interface generated from reading ui file 'configurationpanel.ui'
**
** Created: Thu Feb 10 12:16:26 2005
** Created: Thu Mar 31 11:43:54 2005
** by: The User Interface Compiler ($Id$)
**
** WARNING! All changes made in this file will be lost!
......@@ -119,8 +119,8 @@ public:
QWidget* DriversPage_5;