2
* Copyright (C) 2008-2009 Barracuda Networks, Inc.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23
#include <QCoreApplication>
24
#include <QPluginLoader>
30
#include "psimediaprovider.h"
34
static AudioParams importAudioParams(const PAudioParams &pp)
37
out.setCodec(pp.codec);
38
out.setSampleRate(pp.sampleRate);
39
out.setSampleSize(pp.sampleSize);
40
out.setChannels(pp.channels);
44
static PAudioParams exportAudioParams(const AudioParams &p)
47
out.codec = p.codec();
48
out.sampleRate = p.sampleRate();
49
out.sampleSize = p.sampleSize();
50
out.channels = p.channels();
54
static VideoParams importVideoParams(const PVideoParams &pp)
57
out.setCodec(pp.codec);
63
static PVideoParams exportVideoParams(const VideoParams &p)
66
out.codec = p.codec();
72
static PayloadInfo importPayloadInfo(const PPayloadInfo &pp)
77
out.setClockrate(pp.clockrate);
78
out.setChannels(pp.channels);
79
out.setPtime(pp.ptime);
80
out.setMaxptime(pp.maxptime);
81
QList<PayloadInfo::Parameter> list;
82
foreach(const PPayloadInfo::Parameter &pi, pp.parameters)
84
PayloadInfo::Parameter i;
89
out.setParameters(list);
93
static PPayloadInfo exportPayloadInfo(const PayloadInfo &p)
98
out.clockrate = p.clockrate();
99
out.channels = p.channels();
100
out.ptime = p.ptime();
101
out.maxptime = p.maxptime();
102
QList<PPayloadInfo::Parameter> list;
103
foreach(const PayloadInfo::Parameter &i, p.parameters())
105
PPayloadInfo::Parameter pi;
110
out.parameters = list;
114
//----------------------------------------------------------------------------
116
//----------------------------------------------------------------------------
117
static Provider *g_provider = 0;
118
static QPluginLoader *g_pluginLoader = 0;
120
static void cleanupProvider();
122
static Provider *provider()
126
// static plugin around?
127
Provider *provider = 0;
128
QObjectList list = QPluginLoader::staticInstances();
129
foreach(QObject *obj, list)
131
Plugin *instance = qobject_cast<Plugin *>(obj);
135
Provider *p = instance->createProvider();
145
if(!provider->init(QString()))
151
g_provider = provider;
152
qAddPostRoutine(cleanupProvider);
161
return (provider() ? true : false);
164
PluginResult loadPlugin(const QString &fname, const QString &resourcePath)
167
return PluginSuccess;
169
QPluginLoader *loader = new QPluginLoader(fname);
176
Plugin *instance = qobject_cast<Plugin *>(loader->instance());
183
Provider *provider = instance->createProvider();
191
if(!provider->init(resourcePath))
199
g_provider = provider;
200
g_pluginLoader = loader;
201
qAddPostRoutine(cleanupProvider);
202
return PluginSuccess;
205
void cleanupProvider()
215
g_pluginLoader->unload();
216
delete g_pluginLoader;
228
return provider()->creditName();
233
return provider()->creditText();
236
class Device::Private
247
static Device importDevice(const PDevice &pd)
250
dev.d = new Device::Private;
251
dev.d->type = (Device::Type)pd.type;
253
dev.d->name = pd.name;
258
//----------------------------------------------------------------------------
260
//----------------------------------------------------------------------------
266
Device::Device(const Device &other) :
267
d(other.d ? new Private(*other.d) : 0)
276
Device & Device::operator=(const Device &other)
293
d = new Private(*other.d);
299
bool Device::isNull() const
301
return (d ? false : true);
304
Device::Type Device::type() const
309
QString Device::name() const
314
QString Device::id() const
320
//----------------------------------------------------------------------------
322
//----------------------------------------------------------------------------
323
class VideoWidgetPrivate : public QObject, public VideoWidgetContext
328
friend class VideoWidget;
333
VideoWidgetPrivate(VideoWidget *_q) :
339
virtual QObject *qobject()
344
virtual QWidget *qwidget()
349
virtual void setVideoSize(const QSize &size)
352
emit q->videoSizeChanged();
356
void resized(const QSize &newSize);
357
void paintEvent(QPainter *p);
360
VideoWidget::VideoWidget(QWidget *parent) :
363
d = new VideoWidgetPrivate(this);
366
VideoWidget::~VideoWidget()
371
QSize VideoWidget::sizeHint() const
376
void VideoWidget::paintEvent(QPaintEvent *event)
380
emit d->paintEvent(&p);
383
void VideoWidget::resizeEvent(QResizeEvent *event)
386
emit d->resized(size());
390
//----------------------------------------------------------------------------
392
//----------------------------------------------------------------------------
393
class AudioParams::Private
409
AudioParams::AudioParams() :
414
AudioParams::AudioParams(const AudioParams &other) :
415
d(new Private(*other.d))
419
AudioParams::~AudioParams()
424
AudioParams & AudioParams::operator=(const AudioParams &other)
430
QString AudioParams::codec() const
435
int AudioParams::sampleRate() const
437
return d->sampleRate;
440
int AudioParams::sampleSize() const
442
return d->sampleSize;
445
int AudioParams::channels() const
450
void AudioParams::setCodec(const QString &s)
455
void AudioParams::setSampleRate(int n)
460
void AudioParams::setSampleSize(int n)
465
void AudioParams::setChannels(int n)
470
bool AudioParams::operator==(const AudioParams &other) const
472
if(d->codec == other.d->codec &&
473
d->sampleRate == other.d->sampleRate &&
474
d->sampleSize == other.d->sampleSize &&
475
d->channels == other.d->channels)
483
//----------------------------------------------------------------------------
485
//----------------------------------------------------------------------------
486
class VideoParams::Private
499
VideoParams::VideoParams() :
504
VideoParams::VideoParams(const VideoParams &other) :
505
d(new Private(*other.d))
509
VideoParams::~VideoParams()
514
VideoParams & VideoParams::operator=(const VideoParams &other)
520
QString VideoParams::codec() const
525
QSize VideoParams::size() const
530
int VideoParams::fps() const
535
void VideoParams::setCodec(const QString &s)
540
void VideoParams::setSize(const QSize &s)
545
void VideoParams::setFps(int n)
550
bool VideoParams::operator==(const VideoParams &other) const
552
if(d->codec == other.d->codec &&
553
d->size == other.d->size &&
554
d->fps == other.d->fps)
562
//----------------------------------------------------------------------------
564
//----------------------------------------------------------------------------
565
static QList<Device> importDevices(const QList<PDevice> &in)
568
foreach(const PDevice &pd, in)
569
out += Global::importDevice(pd);
573
static QList<AudioParams> importAudioModes(const QList<PAudioParams> &in)
575
QList<AudioParams> out;
576
foreach(const PAudioParams &pp, in)
577
out += importAudioParams(pp);
581
static QList<VideoParams> importVideoModes(const QList<PVideoParams> &in)
583
QList<VideoParams> out;
584
foreach(const PVideoParams &pp, in)
585
out += importVideoParams(pp);
589
class Features::Private : public QObject
597
QList<Device> audioOutputDevices;
598
QList<Device> audioInputDevices;
599
QList<Device> videoInputDevices;
600
QList<AudioParams> supportedAudioModes;
601
QList<VideoParams> supportedVideoModes;
603
Private(Features *_q) :
607
c = provider()->createFeatures();
608
c->qobject()->setParent(this);
609
connect(c->qobject(), SIGNAL(finished()), SLOT(c_finished()));
619
audioOutputDevices.clear();
620
audioInputDevices.clear();
621
videoInputDevices.clear();
622
supportedAudioModes.clear();
623
supportedVideoModes.clear();
626
void importResults(const PFeatures &in)
628
audioOutputDevices = importDevices(in.audioOutputDevices);
629
audioInputDevices = importDevices(in.audioInputDevices);
630
videoInputDevices = importDevices(in.videoInputDevices);
631
supportedAudioModes = importAudioModes(in.supportedAudioModes);
632
supportedVideoModes = importVideoModes(in.supportedVideoModes);
638
importResults(c->results());
643
Features::Features(QObject *parent) :
646
d = new Private(this);
649
Features::~Features()
654
void Features::lookup(int types)
658
ptypes |= FeaturesContext::AudioOut;
660
ptypes |= FeaturesContext::AudioIn;
662
ptypes |= FeaturesContext::VideoIn;
663
if(types & AudioModes)
664
ptypes |= FeaturesContext::AudioModes;
665
if(types & VideoModes)
666
ptypes |= FeaturesContext::VideoModes;
669
d->c->lookup(ptypes);
672
bool Features::waitForFinished(int msecs)
674
bool ok = d->c->waitForFinished(msecs);
676
d->importResults(d->c->results());
680
QList<Device> Features::audioOutputDevices()
682
return d->audioOutputDevices;
685
QList<Device> Features::audioInputDevices()
687
return d->audioInputDevices;
690
QList<Device> Features::videoInputDevices()
692
return d->videoInputDevices;
695
QList<AudioParams> Features::supportedAudioModes()
697
return d->supportedAudioModes;
700
QList<VideoParams> Features::supportedVideoModes()
702
return d->supportedVideoModes;
705
//----------------------------------------------------------------------------
707
//----------------------------------------------------------------------------
708
class RtpPacket::Private : public QSharedData
714
Private(const QByteArray &_rawValue, int _portOffset) :
716
portOffset(_portOffset)
721
RtpPacket::RtpPacket() :
726
RtpPacket::RtpPacket(const QByteArray &rawValue, int portOffset) :
727
d(new Private(rawValue, portOffset))
731
RtpPacket::RtpPacket(const RtpPacket &other) :
736
RtpPacket::~RtpPacket()
740
RtpPacket & RtpPacket::operator=(const RtpPacket &other)
746
bool RtpPacket::isNull() const
748
return (d ? false : true);
751
QByteArray RtpPacket::rawValue() const
756
int RtpPacket::portOffset() const
758
return d->portOffset;
761
//----------------------------------------------------------------------------
763
//----------------------------------------------------------------------------
764
class RtpChannelPrivate : public QObject
770
RtpChannelContext *c;
772
int readyReadListeners;
774
RtpChannelPrivate(RtpChannel *_q) :
779
readyReadListeners(0)
783
void setContext(RtpChannelContext *_c)
787
c->qobject()->disconnect(this);
788
c->qobject()->setParent(0);
797
c->qobject()->setParent(this);
798
connect(c->qobject(), SIGNAL(readyRead()), SLOT(c_readyRead()));
799
connect(c->qobject(), SIGNAL(packetsWritten(int)), SLOT(c_packetsWritten(int)));
800
connect(c->qobject(), SIGNAL(destroyed()), SLOT(c_destroyed()));
802
if(readyReadListeners > 0)
815
void c_packetsWritten(int count)
817
emit q->packetsWritten(count);
827
RtpChannel::RtpChannel()
829
d = new RtpChannelPrivate(this);
832
RtpChannel::~RtpChannel()
837
int RtpChannel::packetsAvailable() const
840
return d->c->packetsAvailable();
845
RtpPacket RtpChannel::read()
849
PRtpPacket pp = d->c->read();
850
return RtpPacket(pp.rawValue, pp.portOffset);
856
void RtpChannel::write(const RtpPacket &rtp)
863
d->c->setEnabled(true);
867
pp.rawValue = rtp.rawValue();
868
pp.portOffset = rtp.portOffset();
873
void RtpChannel::connectNotify(const char *signal)
875
int oldtotal = d->readyReadListeners;
877
if(QLatin1String(signal) == QMetaObject::normalizedSignature(SIGNAL(readyRead())).data())
878
++d->readyReadListeners;
880
int total = d->readyReadListeners;
881
if(d->c && oldtotal == 0 && total > 0)
884
d->c->setEnabled(true);
888
void RtpChannel::disconnectNotify(const char *signal)
890
int oldtotal = d->readyReadListeners;
892
if(QLatin1String(signal) == QMetaObject::normalizedSignature(SIGNAL(readyRead())).data())
893
--d->readyReadListeners;
895
int total = d->readyReadListeners;
896
if(d->c && oldtotal > 0 && total == 0)
899
d->c->setEnabled(false);
903
//----------------------------------------------------------------------------
905
//----------------------------------------------------------------------------
906
bool PayloadInfo::Parameter::operator==(const PayloadInfo::Parameter &other) const
908
// according to xep-167, parameter names are case-sensitive
909
if(name == other.name && value == other.value)
915
class PayloadInfo::Private
924
QList<PayloadInfo::Parameter> parameters;
935
bool operator==(const Private &other) const
937
// according to xep-167, parameters are unordered
939
name.compare(other.name, Qt::CaseInsensitive) &&
940
clockrate == other.clockrate &&
941
channels == other.channels &&
942
ptime == other.ptime &&
943
maxptime == other.maxptime &&
944
compareUnordered(parameters, other.parameters))
952
static bool compareUnordered(const QList<PayloadInfo::Parameter> &a, const QList<PayloadInfo::Parameter> &b)
954
if(a.count() != b.count())
957
// for every parameter in 'a'
958
foreach(const PayloadInfo::Parameter &p, a)
960
// make sure it is found in 'b'
969
PayloadInfo::PayloadInfo() :
974
PayloadInfo::PayloadInfo(const PayloadInfo &other) :
975
d(new Private(*other.d))
979
PayloadInfo::~PayloadInfo()
984
PayloadInfo & PayloadInfo::operator=(const PayloadInfo &other)
990
bool PayloadInfo::isNull() const
992
return (d->id == -1);
995
int PayloadInfo::id() const
1000
QString PayloadInfo::name() const
1005
int PayloadInfo::clockrate() const
1007
return d->clockrate;
1010
int PayloadInfo::channels() const
1015
int PayloadInfo::ptime() const
1020
int PayloadInfo::maxptime() const
1025
QList<PayloadInfo::Parameter> PayloadInfo::parameters() const
1027
return d->parameters;
1030
void PayloadInfo::setId(int i)
1035
void PayloadInfo::setName(const QString &str)
1040
void PayloadInfo::setClockrate(int i)
1045
void PayloadInfo::setChannels(int num)
1050
void PayloadInfo::setPtime(int i)
1055
void PayloadInfo::setMaxptime(int i)
1060
void PayloadInfo::setParameters(const QList<PayloadInfo::Parameter> ¶ms)
1062
d->parameters = params;
1065
bool PayloadInfo::operator==(const PayloadInfo &other) const
1067
return (*d == *other.d);
1070
//----------------------------------------------------------------------------
1072
//----------------------------------------------------------------------------
1073
class RtpSessionPrivate : public QObject
1079
RtpSessionContext *c;
1080
RtpChannel audioRtpChannel;
1081
RtpChannel videoRtpChannel;
1083
RtpSessionPrivate(RtpSession *_q) :
1087
c = provider()->createRtpSession();
1088
c->qobject()->setParent(this);
1089
connect(c->qobject(), SIGNAL(started()), SLOT(c_started()));
1090
connect(c->qobject(), SIGNAL(preferencesUpdated()), SLOT(c_preferencesUpdated()));
1091
connect(c->qobject(), SIGNAL(audioOutputIntensityChanged(int)), SLOT(c_audioOutputIntensityChanged(int)));
1092
connect(c->qobject(), SIGNAL(audioInputIntensityChanged(int)), SLOT(c_audioInputIntensityChanged(int)));
1093
connect(c->qobject(), SIGNAL(stoppedRecording()), SLOT(c_stoppedRecording()));
1094
connect(c->qobject(), SIGNAL(stopped()), SLOT(c_stopped()));
1095
connect(c->qobject(), SIGNAL(finished()), SLOT(c_finished()));
1096
connect(c->qobject(), SIGNAL(error()), SLOT(c_error()));
1099
~RtpSessionPrivate()
1107
audioRtpChannel.d->setContext(c->audioRtpChannel());
1108
videoRtpChannel.d->setContext(c->videoRtpChannel());
1112
void c_preferencesUpdated()
1114
emit q->preferencesUpdated();
1117
void c_audioOutputIntensityChanged(int intensity)
1119
emit q->audioOutputIntensityChanged(intensity);
1122
void c_audioInputIntensityChanged(int intensity)
1124
emit q->audioInputIntensityChanged(intensity);
1127
void c_stoppedRecording()
1129
emit q->stoppedRecording();
1134
audioRtpChannel.d->setContext(0);
1135
videoRtpChannel.d->setContext(0);
1141
audioRtpChannel.d->setContext(0);
1142
videoRtpChannel.d->setContext(0);
1148
audioRtpChannel.d->setContext(0);
1149
videoRtpChannel.d->setContext(0);
1154
RtpSession::RtpSession(QObject *parent) :
1157
d = new RtpSessionPrivate(this);
1160
RtpSession::~RtpSession()
1165
void RtpSession::reset()
1168
d = new RtpSessionPrivate(this);
1171
void RtpSession::setAudioOutputDevice(const QString &deviceId)
1173
d->c->setAudioOutputDevice(deviceId);
1177
void RtpSession::setVideoOutputWidget(VideoWidget *widget)
1179
d->c->setVideoOutputWidget(widget ? widget->d : 0);
1183
void RtpSession::setAudioInputDevice(const QString &deviceId)
1185
d->c->setAudioInputDevice(deviceId);
1188
void RtpSession::setVideoInputDevice(const QString &deviceId)
1190
d->c->setVideoInputDevice(deviceId);
1193
void RtpSession::setFileInput(const QString &fileName)
1195
d->c->setFileInput(fileName);
1198
void RtpSession::setFileDataInput(const QByteArray &fileData)
1200
d->c->setFileDataInput(fileData);
1203
void RtpSession::setFileLoopEnabled(bool enabled)
1205
d->c->setFileLoopEnabled(enabled);
1209
void RtpSession::setVideoPreviewWidget(VideoWidget *widget)
1211
d->c->setVideoPreviewWidget(widget ? widget->d : 0);
1215
void RtpSession::setRecordingQIODevice(QIODevice *dev)
1217
d->c->setRecorder(dev);
1220
void RtpSession::stopRecording()
1222
d->c->stopRecording();
1225
void RtpSession::setLocalAudioPreferences(const QList<AudioParams> ¶ms)
1227
QList<PAudioParams> list;
1228
foreach(const AudioParams &p, params)
1229
list += exportAudioParams(p);
1230
d->c->setLocalAudioPreferences(list);
1233
void RtpSession::setLocalVideoPreferences(const QList<VideoParams> ¶ms)
1235
QList<PVideoParams> list;
1236
foreach(const VideoParams &p, params)
1237
list += exportVideoParams(p);
1238
d->c->setLocalVideoPreferences(list);
1241
void RtpSession::setMaximumSendingBitrate(int kbps)
1243
d->c->setMaximumSendingBitrate(kbps);
1246
void RtpSession::setRemoteAudioPreferences(const QList<PayloadInfo> &info)
1248
QList<PPayloadInfo> list;
1249
foreach(const PayloadInfo &p, info)
1250
list += exportPayloadInfo(p);
1251
d->c->setRemoteAudioPreferences(list);
1254
void RtpSession::setRemoteVideoPreferences(const QList<PayloadInfo> &info)
1256
QList<PPayloadInfo> list;
1257
foreach(const PayloadInfo &p, info)
1258
list += exportPayloadInfo(p);
1259
d->c->setRemoteVideoPreferences(list);
1262
void RtpSession::start()
1267
void RtpSession::updatePreferences()
1269
d->c->updatePreferences();
1272
void RtpSession::transmitAudio()
1274
d->c->transmitAudio();
1277
void RtpSession::transmitVideo()
1279
d->c->transmitVideo();
1282
void RtpSession::pauseAudio()
1287
void RtpSession::pauseVideo()
1292
void RtpSession::stop()
1297
QList<PayloadInfo> RtpSession::localAudioPayloadInfo() const
1299
QList<PayloadInfo> out;
1300
foreach(const PPayloadInfo &pp, d->c->localAudioPayloadInfo())
1301
out += importPayloadInfo(pp);
1305
QList<PayloadInfo> RtpSession::localVideoPayloadInfo() const
1307
QList<PayloadInfo> out;
1308
foreach(const PPayloadInfo &pp, d->c->localVideoPayloadInfo())
1309
out += importPayloadInfo(pp);
1313
QList<PayloadInfo> RtpSession::remoteAudioPayloadInfo() const
1315
QList<PayloadInfo> out;
1316
foreach(const PPayloadInfo &pp, d->c->remoteAudioPayloadInfo())
1317
out += importPayloadInfo(pp);
1321
QList<PayloadInfo> RtpSession::remoteVideoPayloadInfo() const
1323
QList<PayloadInfo> out;
1324
foreach(const PPayloadInfo &pp, d->c->remoteVideoPayloadInfo())
1325
out += importPayloadInfo(pp);
1329
QList<AudioParams> RtpSession::audioParams() const
1331
QList<AudioParams> out;
1332
foreach(const PAudioParams &pp, d->c->audioParams())
1333
out += importAudioParams(pp);
1337
QList<VideoParams> RtpSession::videoParams() const
1339
QList<VideoParams> out;
1340
foreach(const PVideoParams &pp, d->c->videoParams())
1341
out += importVideoParams(pp);
1345
bool RtpSession::canTransmitAudio() const
1347
return d->c->canTransmitAudio();
1350
bool RtpSession::canTransmitVideo() const
1352
return d->c->canTransmitVideo();
1355
int RtpSession::outputVolume() const
1357
return d->c->outputVolume();
1360
void RtpSession::setOutputVolume(int level)
1362
d->c->setOutputVolume(level);
1365
int RtpSession::inputVolume() const
1367
return d->c->inputVolume();
1370
void RtpSession::setInputVolume(int level)
1372
d->c->setInputVolume(level);
1375
RtpSession::Error RtpSession::errorCode() const
1377
return (RtpSession::Error)d->c->errorCode();
1380
RtpChannel *RtpSession::audioRtpChannel()
1382
return &d->audioRtpChannel;
1385
RtpChannel *RtpSession::videoRtpChannel()
1387
return &d->videoRtpChannel;
1392
#include "psimedia.moc"