1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 19:30:21 +02:00

* Added SipHandler class. This class is supposed to load SIP plugins, manage und communicate with them.

* Our Jabber classes are now a SipPlugin, which gets loaded by SipHandler.
This commit is contained in:
Christian Muehlhaeuser
2010-12-08 12:46:42 +01:00
parent fc49eb7b21
commit fe08bff21c
22 changed files with 527 additions and 372 deletions

View File

@@ -21,8 +21,8 @@ public:
void remove( Tomahawk::Source* s );
QList<Tomahawk::source_ptr> sources() const;
Tomahawk::source_ptr lookup( const QString& username ) const;
Tomahawk::source_ptr lookup( unsigned int id ) const;
Tomahawk::source_ptr get( const QString& username ) const;
Tomahawk::source_ptr get( unsigned int id ) const;
unsigned int count() const;
signals:

View File

@@ -29,10 +29,10 @@
class AudioEngine;
class Database;
class Jabber;
class XMPPBot;
class SipHandler;
class TomahawkZeroconf;
class TomahawkSettings;
class XMPPBot;
namespace Tomahawk
{
@@ -72,6 +72,7 @@ public:
Database* database() { return m_db; }
SourceList& sourcelist() { return m_sources; }
Servent& servent() { return m_servent; }
SipHandler* sipHandler() { return m_sipHandler; }
QNetworkAccessManager* nam() { return m_nam; }
QNetworkProxy* proxy() { return m_proxy; }
Tomahawk::InfoSystem::InfoSystem* infoSystem() { return m_infoSystem; }
@@ -95,17 +96,8 @@ signals:
public slots:
QSharedPointer<QIODevice> getIODeviceForUrl( const Tomahawk::result_ptr& result );
void reconnectJabber();
void jabberAddContact( const QString& jid );
private slots:
void jabberMessage( const QString&, const QString& );
void jabberPeerOffline( const QString& );
void jabberPeerOnline( const QString& );
void jabberAuthError( int code, const QString& msg );
void jabberDisconnected();
void jabberConnected();
void lanHostFound( const QString&, int, const QString&, const QString& );
private:
@@ -114,7 +106,7 @@ private:
void registerMetaTypes();
void startServent();
void setupDatabase();
void setupJabber();
void setupSIP();
void setupPipeline();
void startHTTP();
@@ -127,7 +119,7 @@ private:
Servent m_servent;
SourceList m_sources;
TomahawkZeroconf* m_zeroconf;
QSharedPointer<Jabber> m_jabber;
SipHandler* m_sipHandler;
XMPPBot* m_xmppBot;
#ifndef NO_LIBLASTFM

View File

@@ -43,7 +43,9 @@ SET( tomahawkSources ${tomahawkSources}
audio/audioengine.cpp
utils/tomahawkutils.cpp
jabber/jabber_p.cpp
sip/SipHandler.cpp
sip/SipPlugin.cpp
infosystem/infosystem.cpp
infosystem/infoplugins/echonestplugin.cpp
@@ -205,8 +207,8 @@ SET( tomahawkHeaders ${tomahawkHeaders}
database/databasecommand_updatesearchindex.h
database/databasecollection.h
jabber/jabber.h
jabber/jabber_p.h
sip/SipHandler.h
sip/SipPlugin.h
infosystem/infoplugins/echonestplugin.h
infosystem/infoplugins/musixmatchplugin.h
@@ -329,6 +331,8 @@ IF( UNIX )
INCLUDE( "CMakeLists.unix.txt" )
ENDIF( UNIX )
ADD_SUBDIRECTORY( sip/jabber )
kde4_add_app_icon( tomahawkSources "${CMAKE_CURRENT_SOURCE_DIR}/../data/icons/tomahawk-icon-*.png" )
qt4_add_resources( RC_SRCS "../resources.qrc" )
qt4_wrap_cpp( tomahawkMoc ${tomahawkHeaders} )

View File

@@ -6,7 +6,7 @@ ADD_DEFINITIONS( -fPIC )
SET( GLOOX_LIBS ${GLOOX_LIBS} resolv gloox )
SET( OS_SPECIFIC_LINK_LIBRARIES
SET( OS_SPECIFIC_LINK_LIBRARIES
${LIBLASTFM_LIBRARY}
${GLOOX_LIBS}
qxtweb-standalone

View File

@@ -120,7 +120,7 @@ DatabaseCommand_Resolve::exec( DatabaseImpl* lib )
}
else
{
source_ptr s = APP->sourcelist().lookup( files_query.value( 13 ).toUInt() );
source_ptr s = APP->sourcelist().get( files_query.value( 13 ).toUInt() );
if( s.isNull() )
{
//qDebug() << "Skipping result for offline sourceid:" << files_query.value(13).toUInt();

View File

@@ -1,115 +0,0 @@
#ifndef JABBER_H
#define JABBER_H
/*
Pimpl of jabber_p, which inherits from a gazillion gloox classes
and it littered with public methods.
*/
#include "jabber_p.h"
class Jabber : public QObject
{
Q_OBJECT
public:
Jabber( const QString &jid, const QString password, const QString server = "", const int port=-1 )
: p( jid, password, server, port )
{
}
~Jabber()
{
// p.disconnect();
}
void setProxy( QNetworkProxy* proxy )
{
p.setProxy( proxy );
}
public slots:
void start()
{
//connect( &p, SIGNAL( finished() ),
// this, SIGNAL( finished() ) );
connect( &p, SIGNAL( msgReceived( QString, QString ) ),
this, SIGNAL( msgReceived( QString, QString ) ) );
connect( &p, SIGNAL( peerOnline( QString ) ),
this, SIGNAL( peerOnline( QString ) ) );
connect( &p, SIGNAL( peerOffline( QString ) ),
this, SIGNAL( peerOffline( QString ) ) );
connect( &p, SIGNAL( connected() ),
this, SIGNAL( connected() ) );
connect( &p, SIGNAL( disconnected() ),
this, SIGNAL( disconnected() ) );
connect( &p, SIGNAL( jidChanged( QString ) ),
this, SIGNAL( jidChanged( QString ) ) );
connect( &p, SIGNAL( authError( int, const QString& ) ),
this, SIGNAL( authError( int, const QString& ) ) );
p.go();
}
void disconnect()
{
QMetaObject::invokeMethod( &p,
"disconnect",
Qt::QueuedConnection
);
}
void sendMsg( const QString& to, const QString& msg )
{
QMetaObject::invokeMethod( &p,
"sendMsg",
Qt::QueuedConnection,
Q_ARG(const QString, to),
Q_ARG(const QString, msg)
);
}
void broadcastMsg( const QString &msg )
{
QMetaObject::invokeMethod( &p,
"broadcastMsg",
Qt::QueuedConnection,
Q_ARG(const QString, msg)
);
}
void addContact( const QString &jid, const QString& msg = QString() )
{
QMetaObject::invokeMethod( &p,
"addContact",
Qt::QueuedConnection,
Q_ARG(const QString, jid),
Q_ARG(const QString, msg)
);
}
signals:
//void finished();
void msgReceived( const QString&, const QString& );
void peerOnline( const QString& );
void peerOffline( const QString& );
void connected();
void disconnected();
void jidChanged( const QString& );
void authError( int, const QString& );
private:
Jabber_p p;
};
#endif

View File

@@ -572,7 +572,7 @@ Servent::remoteIODeviceFactory( const result_ptr& result )
QStringList parts = result->url().mid( QString( "servent://" ).length()).split( "\t" );
const QString& sourceName = parts.at( 0 );
const QString& fileId = parts.at( 1 );
const source_ptr& s = TomahawkApp::instance()->sourcelist().lookup( sourceName );
const source_ptr& s = TomahawkApp::instance()->sourcelist().get( sourceName );
if ( s.isNull() )
return sp;

View File

@@ -4,6 +4,7 @@
#include <QCryptographicHash>
#include <QDebug>
#include <QDesktopServices>
#include <QFileDialog>
#include <QMessageBox>
#include <QNetworkProxy>
@@ -16,7 +17,7 @@
#include "tomahawk/tomahawkapp.h"
#include "musicscanner.h"
#include "tomahawksettings.h"
#include <QDesktopServices>
#include "sip/SipHandler.h"
static QString
@@ -121,7 +122,8 @@ SettingsDialog::~SettingsDialog()
if( rejabber )
{
APP->reconnectJabber();
APP->sipHandler()->disconnect();
APP->sipHandler()->connect();
}
}
else

198
src/sip/SipHandler.cpp Normal file
View File

@@ -0,0 +1,198 @@
#include "SipHandler.h"
#include "sip/SipPlugin.h"
#include <QDir>
#include <QPluginLoader>
#include <QMessageBox>
#include "tomahawk/tomahawkapp.h"
#include "controlconnection.h"
SipHandler::SipHandler( QObject* parent )
: QObject( parent )
{
loadPlugins();
}
SipHandler::~SipHandler()
{
}
void
SipHandler::loadPlugins()
{
qDebug() << TomahawkApp::instance();
qDebug() << TomahawkApp::instance()->applicationDirPath();
QDir pluginsDir( TomahawkApp::instance()->applicationDirPath() );
foreach ( QString fileName, pluginsDir.entryList( QDir::Files ) )
{
QPluginLoader loader( pluginsDir.absoluteFilePath( fileName ) );
QObject* plugin = loader.instance();
if ( plugin )
{
// Connect via that plugin
qDebug() << "Trying to load plugin:" << loader.fileName();
loadPlugin( plugin );
}
}
}
void
SipHandler::loadPlugin( QObject* plugin )
{
SipPlugin* sip = qobject_cast<SipPlugin*>(plugin);
if ( sip )
{
qDebug() << "Loaded plugin!";
QObject::connect( sip, SIGNAL( peerOnline( QString ) ), SLOT( onPeerOnline( QString ) ) );
QObject::connect( sip, SIGNAL( peerOffline( QString ) ), SLOT( onPeerOffline( QString ) ) );
QObject::connect( sip, SIGNAL( msgReceived( QString, QString ) ), SLOT( onMessage( QString, QString ) ) );
QObject::connect( sip, SIGNAL( connected() ), SIGNAL( connected() ) );
QObject::connect( sip, SIGNAL( disconnected() ), SIGNAL( disconnected() ) );
QObject::connect( sip, SIGNAL( error( int, QString ) ), SLOT( onError( int, QString ) ) );
m_plugins << sip;
}
}
void
SipHandler::connect()
{
foreach( SipPlugin* sip, m_plugins )
sip->connect();
}
void
SipHandler::disconnect()
{
foreach( SipPlugin* sip, m_plugins )
sip->disconnect();
}
void
SipHandler::onPeerOnline( const QString& jid )
{
// qDebug() << Q_FUNC_INFO;
qDebug() << "Jabber online:" << jid;
SipPlugin* sip = qobject_cast<SipPlugin*>(sender());
QVariantMap m;
if( APP->servent().visibleExternally() )
{
QString key = uuid();
ControlConnection* conn = new ControlConnection( &APP->servent() );
const QString& nodeid = APP->nodeID();
conn->setName( jid.left( jid.indexOf( "/" ) ) );
conn->setId( nodeid );
// FIXME strip /resource, but we should use a UID per database install
//QString uniqname = jid.left( jid.indexOf("/") );
//conn->setName( uniqname ); //FIXME
// FIXME:
//QString ouruniqname = m_settings->value( "jabber/username" ).toString()
// .left( m_settings->value( "jabber/username" ).toString().indexOf("/") );
APP->servent().registerOffer( key, conn );
m["visible"] = true;
m["ip"] = APP->servent().externalAddress().toString();
m["port"] = APP->servent().externalPort();
m["key"] = key;
m["uniqname"] = nodeid;
qDebug() << "Asking them to connect to us:" << m;
}
else
{
m["visible"] = false;
qDebug() << "We are not visible externally:" << m;
}
QJson::Serializer ser;
QByteArray ba = ser.serialize( m );
sip->sendMsg( jid, QString::fromAscii( ba ) );
}
void
SipHandler::onPeerOffline( const QString& jid )
{
// qDebug() << Q_FUNC_INFO;
qDebug() << "Jabber offline:" << jid;
}
void
SipHandler::onMessage( const QString& from, const QString& msg )
{
qDebug() << Q_FUNC_INFO;
qDebug() << "Jabber Message:" << from << msg;
QJson::Parser parser;
bool ok;
QVariant v = parser.parse( msg.toAscii(), &ok );
if ( !ok || v.type() != QVariant::Map )
{
qDebug() << "Invalid JSON in XMPP msg";
return;
}
QVariantMap m = v.toMap();
/*
If only one party is externally visible, connection is obvious
If both are, peer with lowest IP address initiates the connection.
This avoids dupe connections.
*/
if ( m.value( "visible" ).toBool() )
{
if( !APP->servent().visibleExternally() ||
APP->servent().externalAddress().toString() <= m.value( "ip" ).toString() )
{
qDebug() << "Initiate connection to" << from;
APP->servent().connectToPeer( m.value( "ip" ).toString(),
m.value( "port" ).toInt(),
m.value( "key" ).toString(),
from,
m.value( "uniqname" ).toString() );
}
else
{
qDebug() << Q_FUNC_INFO << "They should be conecting to us...";
}
}
else
{
qDebug() << Q_FUNC_INFO << "They are not visible, doing nothing atm";
// if ( m_servent.visibleExternally() )
// jabberPeerOnline( from ); // HACK FIXME
}
}
void
SipHandler::onError( int code, const QString& msg )
{
qWarning() << "Failed to connect to SIP:" << code << msg;
if ( code == SipPlugin::AuthError )
{
emit authError();
}
else
{
// QTimer::singleShot( 10000, this, SLOT( reconnectJabber() ) );
}
}

43
src/sip/SipHandler.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef SIPHANDLER_H
#define SIPHANDLER_H
#include <QDebug>
#include <QObject>
class SipPlugin;
class SipHandler : public QObject
{
Q_OBJECT
public:
// static SipHandler* instance() { return s_instance ? s_instance : new SipHandler(); }
SipHandler( QObject* parent );
~SipHandler();
public slots:
void addContact( const QString& id ) { qDebug() << Q_FUNC_INFO << id; }
void connect();
void disconnect();
signals:
void connected();
void disconnected();
void authError();
private slots:
void onMessage( const QString&, const QString& );
void onPeerOffline( const QString& );
void onPeerOnline( const QString& );
void onError( int code, const QString& msg );
private:
void loadPlugins();
void loadPlugin( QObject* plugin );
QList< SipPlugin* > m_plugins;
};
#endif

2
src/sip/SipPlugin.cpp Normal file
View File

@@ -0,0 +1,2 @@
#include <sip/SipPlugin.h>

34
src/sip/SipPlugin.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef SIPPLUGIN_H
#define SIPPLUGIN_H
#include <QObject>
#include <QString>
class SipPlugin : public QObject
{
Q_OBJECT
public:
enum SipErrorCode { AuthError, ConnectionError }; // Placeholder for errors, to be defined
virtual ~SipPlugin() {}
virtual bool connect() = 0;
virtual void disconnect() = 0;
virtual void addContact( const QString &jid, const QString& msg = QString() ) = 0;
virtual void sendMsg( const QString& to, const QString& msg ) = 0;
signals:
void error( int, const QString& );
void connected();
void disconnected();
void peerOnline( const QString& );
void peerOffline( const QString& );
void msgReceived( const QString&, const QString& );
};
Q_DECLARE_INTERFACE( SipPlugin, "tomahawk.Sip/1.0" )
#endif

View File

@@ -0,0 +1,30 @@
project( tomahawk )
include( ${QT_USE_FILE} )
add_definitions( ${QT_DEFINITIONS} )
add_definitions( -DQT_PLUGIN )
add_definitions( -DQT_SHARED )
set( jabberSources
jabber.cpp
jabber_p.cpp
)
set( jabberHeaders
jabber.h
jabber_p.h
)
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
${QT_INCLUDE_DIR}
)
qt4_wrap_cpp( jabberMoc ${jabberHeaders} )
add_library( sip_jabber SHARED ${jabberSources} ${jabberMoc} )
target_link_libraries( sip_jabber
${QT_LIBRARIES}
${GLOOX_LIBS}
)
install( TARGETS sip_jabber DESTINATION . )

63
src/sip/jabber/jabber.cpp Normal file
View File

@@ -0,0 +1,63 @@
#include "jabber.h"
#include "tomahawk/tomahawkapp.h"
#include "tomahawksettings.h"
void
JabberPlugin::setProxy( QNetworkProxy* proxy )
{
p->setProxy( proxy );
}
bool
JabberPlugin::connect()
{
if ( !APP->settings()->value( "jabber/autoconnect", true ).toBool() )
return false;
QString jid = APP->settings()->value( "jabber/username" ).toString();
QString server = APP->settings()->value( "jabber/server" ).toString();
QString password = APP->settings()->value( "jabber/password" ).toString();
unsigned int port = APP->settings()->value( "jabber/port", 5222 ).toUInt();
// gtalk check
if( server.isEmpty() && ( jid.contains( "@gmail.com" ) || jid.contains( "@googlemail.com" ) ) )
{
qDebug() << "Setting jabber server to talk.google.com";
server = "talk.google.com";
}
if ( port < 1 || port > 65535 || jid.isEmpty() || password.isEmpty() )
{
qDebug() << "Jabber credentials look wrong, not connecting";
return false;
}
p = new Jabber_p( jid, password, server, port );
QObject::connect( p, SIGNAL( peerOnline( QString ) ), SIGNAL( peerOnline( QString ) ) );
QObject::connect( p, SIGNAL( peerOffline( QString ) ), SIGNAL( peerOffline( QString ) ) );
QObject::connect( p, SIGNAL( msgReceived( QString, QString ) ), SIGNAL( msgReceived( QString, QString ) ) );
QObject::connect( p, SIGNAL( connected() ), SIGNAL( connected() ) );
QObject::connect( p, SIGNAL( disconnected() ), SIGNAL( disconnected() ) );
QObject::connect( p, SIGNAL( authError( int, QString ) ), SLOT( onAuthError( int, QString ) ) );
p->go();
return true;
}
void
JabberPlugin::onAuthError( int code, const QString& message )
{
if ( code == gloox::ConnAuthenticationFailed )
emit error( SipPlugin::AuthError, message );
else
emit error( SipPlugin::ConnectionError, message );
}
Q_EXPORT_PLUGIN2( sip, JabberPlugin )

68
src/sip/jabber/jabber.h Normal file
View File

@@ -0,0 +1,68 @@
#ifndef JABBER_H
#define JABBER_H
#include "SipPlugin.h"
#include "jabber_p.h"
class JabberPlugin : public SipPlugin
{
Q_OBJECT
Q_INTERFACES( SipPlugin )
public:
JabberPlugin()
: p( 0 )
{}
virtual ~JabberPlugin() { delete p; }
void setProxy( QNetworkProxy* proxy );
virtual bool connect();
public slots:
void disconnect()
{
QMetaObject::invokeMethod( p,
"disconnect",
Qt::QueuedConnection
);
}
void sendMsg( const QString& to, const QString& msg )
{
QMetaObject::invokeMethod( p,
"sendMsg",
Qt::QueuedConnection,
Q_ARG(const QString, to),
Q_ARG(const QString, msg)
);
}
void broadcastMsg( const QString &msg )
{
QMetaObject::invokeMethod( p,
"broadcastMsg",
Qt::QueuedConnection,
Q_ARG(const QString, msg)
);
}
void addContact( const QString &jid, const QString& msg = QString() )
{
QMetaObject::invokeMethod( p,
"addContact",
Qt::QueuedConnection,
Q_ARG(const QString, jid),
Q_ARG(const QString, msg)
);
}
private slots:
void onAuthError( int, const QString& );
private:
Jabber_p* p;
};
#endif

View File

@@ -79,7 +79,7 @@ SourceList::sources() const
source_ptr
SourceList::lookup( unsigned int id ) const
SourceList::get( unsigned int id ) const
{
QMutexLocker lock( &m_mut );
return m_sources.value( m_sources_id2name.value( id ) );
@@ -87,7 +87,7 @@ SourceList::lookup( unsigned int id ) const
source_ptr
SourceList::lookup( const QString& username ) const
SourceList::get( const QString& username ) const
{
QMutexLocker lock( &m_mut );
return m_sources.value( username );

View File

@@ -14,14 +14,13 @@
#include "database/databasecollection.h"
#include "database/databasecommand_collectionstats.h"
#include "database/databaseresolver.h"
#include "jabber/jabber.h"
#include "sip/SipHandler.h"
#include "utils/tomahawkutils.h"
#include "xmppbot/xmppbot.h"
#include "web/api_v1.h"
#include "scriptresolver.h"
#include "audioengine.h"
#include "controlconnection.h"
#include "tomahawkzeroconf.h"
#ifndef TOMAHAWK_HEADLESS
@@ -154,16 +153,6 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
m_nam = new QNetworkAccessManager;
#endif
#ifndef TOMAHAWK_HEADLESS
if ( !m_headless )
{
m_mainwindow = new TomahawkWindow();
m_mainwindow->setWindowTitle( "Tomahawk" );
m_mainwindow->show();
connect( m_mainwindow, SIGNAL( settingsChanged() ), SIGNAL( settingsChanged() ) );
}
#endif
// Set up proxy
if( m_settings->proxyType() != QNetworkProxy::NoProxy && !m_settings->proxyHost().isEmpty() )
{
@@ -185,6 +174,22 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
boost::bind( &TomahawkApp::httpIODeviceFactory, this, _1 );
this->registerIODeviceFactory( "http", fac );
if( !arguments().contains("--nojabber") )
{
setupSIP();
m_xmppBot = new XMPPBot( this );
}
#ifndef TOMAHAWK_HEADLESS
if ( !m_headless )
{
m_mainwindow = new TomahawkWindow();
m_mainwindow->setWindowTitle( "Tomahawk" );
m_mainwindow->show();
connect( m_mainwindow, SIGNAL( settingsChanged() ), SIGNAL( settingsChanged() ) );
}
#endif
setupPipeline();
initLocalCollection();
startServent();
@@ -193,9 +198,6 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
if( arguments().contains( "--http" ) || settings()->value( "network/http", true ).toBool() )
startHTTP();
if( !arguments().contains("--nojabber") ) setupJabber();
m_xmppBot = new XMPPBot( this );
if ( !arguments().contains( "--nozeroconf" ) )
{
// advertise our servent on the LAN
@@ -205,12 +207,14 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
m_zeroconf->advertise();
}
#ifndef TOMAHAWK_HEADLESS
m_sipHandler->connect();
#ifndef TOMAHAWK_HEADLESS
if ( !m_settings->hasScannerPath() )
{
m_mainwindow->showSettingsDialog();
}
#endif
#endif
}
@@ -218,10 +222,7 @@ TomahawkApp::~TomahawkApp()
{
qDebug() << Q_FUNC_INFO;
if ( !m_jabber.isNull() )
{
m_jabber.clear();
}
delete m_sipHandler;
#ifndef TOMAHAWK_HEADLESS
delete m_mainwindow;
@@ -432,218 +433,13 @@ TomahawkApp::loadPlugins()
void
TomahawkApp::setupJabber()
{
qDebug() << Q_FUNC_INFO;
if ( !m_jabber.isNull() )
return;
if ( !m_settings->value( "jabber/autoconnect", true ).toBool() )
return;
QString jid = m_settings->value( "jabber/username" ).toString();
QString server = m_settings->value( "jabber/server" ).toString();
QString password = m_settings->value( "jabber/password" ).toString();
unsigned int port = m_settings->value( "jabber/port", 5222 ).toUInt();
// gtalk check
if( server.isEmpty() && ( jid.contains("@gmail.com") || jid.contains("@googlemail.com") ) )
{
qDebug() << "Setting jabber server to talk.google.com";
server = "talk.google.com";
}
if ( port < 1 || port > 65535 || jid.isEmpty() || password.isEmpty() )
{
qDebug() << "Jabber credentials look wrong, not connecting";
return;
}
m_jabber = QSharedPointer<Jabber>( new Jabber( jid, password, server, port ) );
connect( m_jabber.data(), SIGNAL( peerOnline( QString ) ), SLOT( jabberPeerOnline( QString ) ) );
connect( m_jabber.data(), SIGNAL( peerOffline( QString ) ), SLOT( jabberPeerOffline( QString ) ) );
connect( m_jabber.data(), SIGNAL( msgReceived( QString, QString ) ), SLOT( jabberMessage( QString, QString ) ) );
connect( m_jabber.data(), SIGNAL( connected() ), SLOT( jabberConnected() ) );
connect( m_jabber.data(), SIGNAL( disconnected() ), SLOT( jabberDisconnected() ) );
connect( m_jabber.data(), SIGNAL( authError( int, QString ) ), SLOT( jabberAuthError( int, QString ) ) );
m_jabber->setProxy( m_proxy );
m_jabber->start();
}
void
TomahawkApp::reconnectJabber()
{
m_jabber.clear();
setupJabber();
}
void
TomahawkApp::jabberAddContact( const QString& jid )
{
m_jabber->addContact( jid );
}
void
TomahawkApp::jabberAuthError( int code, const QString& msg )
{
qWarning() << "Failed to connect to jabber" << code << msg;
#ifndef TOMAHAWK_HEADLESS
if( m_mainwindow )
{
m_mainwindow->setWindowTitle( QString("Tomahawk [jabber: %1, portfwd: %2]")
.arg( "AUTH_ERROR" )
.arg( (servent().externalPort() > 0) ? QString( "YES:%1" ).arg(servent().externalPort()) :"NO" ) );
if ( code == gloox::ConnAuthenticationFailed )
{
QMessageBox::warning( m_mainwindow,
"Jabber Auth Error",
QString("Error connecting to Jabber (%1) %2").arg(code).arg(msg),
QMessageBox::Ok );
}
}
#endif
if ( code != gloox::ConnAuthenticationFailed )
QTimer::singleShot( 10000, this, SLOT( reconnectJabber() ) );
}
void
TomahawkApp::jabberConnected()
TomahawkApp::setupSIP()
{
qDebug() << Q_FUNC_INFO;
#ifndef TOMAHAWK_HEADLESS
if( m_mainwindow )
{
m_mainwindow->setWindowTitle( QString("Tomahawk [jabber: %1, portfwd: %2]")
.arg( "CONNECTED" )
.arg( (servent().externalPort() > 0) ? QString( "YES:%1" ).arg(servent().externalPort()):"NO" ) );
}
#endif
}
m_sipHandler = new SipHandler( this );
void
TomahawkApp::jabberDisconnected()
{
qDebug() << Q_FUNC_INFO;
#ifndef TOMAHAWK_HEADLESS
if( m_mainwindow )
{
m_mainwindow->setWindowTitle( QString("Tomahawk [jabber: %1, portfwd: %2]")
.arg( "DISCONNECTED" )
.arg( (servent().externalPort() > 0) ? QString( "YES:%1" ).arg(servent().externalPort()):"NO" ) );
}
#endif
}
void
TomahawkApp::jabberPeerOnline( const QString& jid )
{
// qDebug() << Q_FUNC_INFO;
// qDebug() << "Jabber Peer online:" << jid;
QVariantMap m;
if( m_servent.visibleExternally() )
{
QString key = uuid();
ControlConnection* conn = new ControlConnection( &m_servent );
const QString& nodeid = APP->nodeID();
conn->setName( jid.left( jid.indexOf( "/" ) ) );
conn->setId( nodeid );
// FIXME strip /resource, but we should use a UID per database install
//QString uniqname = jid.left( jid.indexOf("/") );
//conn->setName( uniqname ); //FIXME
// FIXME:
//QString ouruniqname = m_settings->value( "jabber/username" ).toString()
// .left( m_settings->value( "jabber/username" ).toString().indexOf("/") );
m_servent.registerOffer( key, conn );
m["visible"] = true;
m["ip"] = m_servent.externalAddress().toString();
m["port"] = m_servent.externalPort();
m["key"] = key;
m["uniqname"] = nodeid;
qDebug() << "Asking them to connect to us:" << m;
}
else
{
m["visible"] = false;
qDebug() << "We are not visible externally:" << m;
}
QJson::Serializer ser;
QByteArray ba = ser.serialize( m );
m_jabber->sendMsg( jid, QString::fromAscii( ba ) );
}
void
TomahawkApp::jabberPeerOffline( const QString& jid )
{
// qDebug() << Q_FUNC_INFO;
// qDebug() << "Jabber Peer offline:" << jid;
}
void
TomahawkApp::jabberMessage( const QString& from, const QString& msg )
{
qDebug() << Q_FUNC_INFO;
qDebug() << "Jabber Message:" << from << msg;
QJson::Parser parser;
bool ok;
QVariant v = parser.parse( msg.toAscii(), &ok );
if ( !ok || v.type() != QVariant::Map )
{
qDebug() << "Invalid JSON in XMPP msg";
return;
}
QVariantMap m = v.toMap();
/*
If only one party is externally visible, connection is obvious
If both are, peer with lowest IP address initiates the connection.
This avoids dupe connections.
*/
if ( m.value( "visible" ).toBool() )
{
if( !m_servent.visibleExternally() ||
m_servent.externalAddress().toString() <= m.value( "ip" ).toString() )
{
qDebug() << "Initiate connection to" << from;
m_servent.connectToPeer( m.value( "ip" ).toString(),
m.value( "port" ).toInt(),
m.value( "key" ).toString(),
from,
m.value( "uniqname" ).toString() );
}
else
{
qDebug() << Q_FUNC_INFO << "They should be conecting to us...";
}
}
else
{
qDebug() << Q_FUNC_INFO << "They are not visible, doing nothing atm";
// if ( m_servent.visibleExternally() )
// jabberPeerOnline( from ); // HACK FIXME
}
// m_sipHandler->setProxy( m_proxy );
}

View File

@@ -20,6 +20,8 @@
#include "database/databasecommand_collectionstats.h"
#include "topbar/topbar.h"
#include "sip/SipHandler.h"
#include "audiocontrols.h"
#include "controlconnection.h"
#include "database.h"
@@ -168,6 +170,11 @@ TomahawkWindow::setupSignals()
connect( ui->actionCreatePlaylist, SIGNAL( triggered() ), SLOT( createPlaylist() ));
connect( ui->actionAboutTomahawk, SIGNAL( triggered() ), SLOT( showAboutTomahawk() ) );
connect( ui->actionExit, SIGNAL( triggered() ), APP, SLOT( quit() ) );
// <SipHandler>
connect( APP->sipHandler(), SIGNAL( connected() ), SLOT( onSipConnected() ) );
connect( APP->sipHandler(), SIGNAL( disconnected() ), SLOT( onSipDisconnected() ) );
connect( APP->sipHandler(), SIGNAL( authError() ), SLOT( onSipError() ) );
}
@@ -293,7 +300,7 @@ TomahawkWindow::addFriendManually()
return;
qDebug() << "Attempting to add jabber contact to roster:" << id;
APP->jabberAddContact( id );
APP->sipHandler()->addContact( id );
}
@@ -338,6 +345,32 @@ TomahawkWindow::onPlaybackLoading( const Tomahawk::result_ptr& result )
}
void
TomahawkWindow::onSipConnected()
{
ui->statusButton->setText( tr( "Online" ) );
}
void
TomahawkWindow::onSipDisconnected()
{
ui->statusButton->setText( tr( "Offline" ) );
}
void
TomahawkWindow::onSipError()
{
onSipDisconnected();
QMessageBox::warning( this,
tr( "Authentication Error" ),
QString( "Error connecting to SIP: Authentication failed!" ),
QMessageBox::Ok );
}
void
TomahawkWindow::setWindowTitle( const QString& title )
{

View File

@@ -50,6 +50,11 @@ public slots:
private slots:
void scanFinished();
void rescanCollectionManually();
void onSipConnected();
void onSipDisconnected();
void onSipError();
void addPeerManually();
void addFriendManually();

View File

@@ -23,9 +23,9 @@
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<widget class="QPushButton" name="statusButton">
<property name="text">
<string>PushButton</string>
<string></string>
</property>
</widget>
</item>