1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-04-20 07:52:30 +02:00

Return IODevices for track URLs through callbacks.

This commit is contained in:
Teo Mrnjavac 2013-03-14 16:08:24 +01:00
parent 20bfb48be7
commit 230fbdcef9
10 changed files with 151 additions and 61 deletions

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -39,6 +40,8 @@
#include "utils/Logger.h"
#include "playlist/SingleTrackPlaylistInterface.h"
#include <boost/bind.hpp>
#include <QtCore/QUrl>
#include <QDir>
#include <QtNetwork/QNetworkReply>
@ -430,30 +433,43 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
}
bool
void
AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
{
if ( result.isNull() )
{
stop();
return;
}
setCurrentTrack( result );
if ( !TomahawkUtils::isHttpResult( m_currentTrack->url() ) &&
!TomahawkUtils::isLocalResult( m_currentTrack->url() ) )
{
boost::function< void ( QSharedPointer< QIODevice >& ) > callback =
boost::bind( &AudioEngine::performLoadTrack, this, result, _1 );
Servent::instance()->getIODeviceForUrl( m_currentTrack, callback );
}
else
{
QSharedPointer< QIODevice > io;
performLoadTrack( result, io );
}
}
void
AudioEngine::performLoadTrack( const Tomahawk::result_ptr& result, QSharedPointer< QIODevice >& io )
{
bool err = false;
{
QSharedPointer<QIODevice> io;
if ( result.isNull() )
err = true;
else
if ( !TomahawkUtils::isHttpResult( m_currentTrack->url() ) &&
!TomahawkUtils::isLocalResult( m_currentTrack->url() ) &&
( !io || io.isNull() ) )
{
setCurrentTrack( result );
if ( !TomahawkUtils::isHttpResult( m_currentTrack->url() ) &&
!TomahawkUtils::isLocalResult( m_currentTrack->url() ) )
{
io = Servent::instance()->getIODeviceForUrl( m_currentTrack );
if ( !io || io.isNull() )
{
tLog() << "Error getting iodevice for" << result->url();
err = true;
}
}
tLog() << "Error getting iodevice for" << result->url();
err = true;
}
if ( !err )
@ -520,11 +536,11 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
if ( err )
{
stop();
return false;
return;
}
m_waitingOnNewTrack = false;
return true;
return;
}

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -128,7 +129,8 @@ signals:
void error( AudioEngine::AudioErrorCode errorCode );
private slots:
bool loadTrack( const Tomahawk::result_ptr& result );
void loadTrack( const Tomahawk::result_ptr& result ); //async!
void performLoadTrack( const Tomahawk::result_ptr& result, QSharedPointer< QIODevice >& io ); //only call from loadTrack kthxbi
void loadPreviousTrack();
void loadNextTrack();

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -75,17 +76,18 @@ Servent::Servent( QObject* parent )
setProxy( QNetworkProxy::NoProxy );
{
boost::function<QSharedPointer<QIODevice>(result_ptr)> fac = boost::bind( &Servent::localFileIODeviceFactory, this, _1 );
// _1 = result, _2 = callback function for IODevice
IODeviceFactoryFunc fac = boost::bind( &Servent::localFileIODeviceFactory, this, _1, _2 );
this->registerIODeviceFactory( "file", fac );
}
{
boost::function<QSharedPointer<QIODevice>(result_ptr)> fac = boost::bind( &Servent::remoteIODeviceFactory, this, _1 );
IODeviceFactoryFunc fac = boost::bind( &Servent::remoteIODeviceFactory, this, _1, _2 );
this->registerIODeviceFactory( "servent", fac );
}
{
boost::function<QSharedPointer<QIODevice>(result_ptr)> fac = boost::bind( &Servent::httpIODeviceFactory, this, _1 );
IODeviceFactoryFunc fac = boost::bind( &Servent::httpIODeviceFactory, this, _1, _2 );
this->registerIODeviceFactory( "http", fac );
this->registerIODeviceFactory( "https", fac );
}
@ -944,8 +946,9 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString
}
QSharedPointer<QIODevice>
Servent::remoteIODeviceFactory( const result_ptr& result )
void
Servent::remoteIODeviceFactory( const Tomahawk::result_ptr& result,
boost::function< void ( QSharedPointer< QIODevice >& ) > callback )
{
QSharedPointer<QIODevice> sp;
@ -954,12 +957,18 @@ Servent::remoteIODeviceFactory( const result_ptr& result )
const QString fileId = parts.at( 1 );
source_ptr s = SourceList::instance()->get( sourceName );
if ( s.isNull() || !s->controlConnection() )
return sp;
{
callback( sp );
return;
}
ControlConnection* cc = s->controlConnection();
StreamConnection* sc = new StreamConnection( this, cc, fileId, result );
createParallelConnection( cc, sc, QString( "FILE_REQUEST_KEY:%1" ).arg( fileId ) );
return sc->iodevice();
//boost::functions cannot accept temporaries as parameters
sp = sc->iodevice();
callback( sp );
}
@ -1066,45 +1075,61 @@ Servent::triggerDBSync()
void
Servent::registerIODeviceFactory( const QString &proto, boost::function<QSharedPointer<QIODevice>(Tomahawk::result_ptr)> fac )
Servent::registerIODeviceFactory( const QString &proto,
IODeviceFactoryFunc fac )
{
m_iofactories.insert( proto, fac );
}
QSharedPointer<QIODevice>
Servent::getIODeviceForUrl( const Tomahawk::result_ptr& result )
void
Servent::getIODeviceForUrl( const Tomahawk::result_ptr& result,
boost::function< void ( QSharedPointer< QIODevice >& ) > callback )
{
QSharedPointer<QIODevice> sp;
QRegExp rx( "^([a-zA-Z0-9]+)://(.+)$" );
if ( rx.indexIn( result->url() ) == -1 )
return sp;
{
callback( sp );
return;
}
const QString proto = rx.cap( 1 );
if ( !m_iofactories.contains( proto ) )
return sp;
{
callback( sp );
return;
}
return m_iofactories.value( proto )( result );
//QtScriptResolverHelper::customIODeviceFactory is async!
m_iofactories.value( proto )( result, callback );
}
QSharedPointer<QIODevice>
Servent::localFileIODeviceFactory( const Tomahawk::result_ptr& result )
void
Servent::localFileIODeviceFactory( const Tomahawk::result_ptr& result,
boost::function< void ( QSharedPointer< QIODevice >& ) > callback )
{
// ignore "file://" at front of url
QFile* io = new QFile( result->url().mid( QString( "file://" ).length() ) );
if ( io )
io->open( QIODevice::ReadOnly );
return QSharedPointer<QIODevice>( io );
//boost::functions cannot accept temporaries as parameters
QSharedPointer< QIODevice > sp = QSharedPointer<QIODevice>( io );
callback( sp );
}
QSharedPointer<QIODevice>
Servent::httpIODeviceFactory( const Tomahawk::result_ptr& result )
void
Servent::httpIODeviceFactory( const Tomahawk::result_ptr& result,
boost::function< void ( QSharedPointer< QIODevice >& ) > callback )
{
QNetworkRequest req( result->url() );
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
return QSharedPointer<QIODevice>( reply, &QObject::deleteLater );
//boost::functions cannot accept temporaries as parameters
QSharedPointer< QIODevice > sp = QSharedPointer< QIODevice >( reply, &QObject::deleteLater );
callback( sp );
}

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -54,6 +55,9 @@ class PortFwdThread;
class PeerInfo;
class SipInfo;
typedef boost::function< void( const Tomahawk::result_ptr&,
boost::function< void( QSharedPointer< QIODevice >& ) > )> IODeviceFactoryFunc;
// this is used to hold a bit of state, so when a connected signal is emitted
// from a socket, we can associate it with a Connection object etc.
class DLLEXPORT QTcpSocketExtra : public QTcpSocket
@ -121,7 +125,6 @@ public:
QString externalAddress() const { return !m_externalHostname.isNull() ? m_externalHostname : m_externalAddress.toString(); }
int externalPort() const { return m_externalPort; }
QSharedPointer< QIODevice > remoteIODeviceFactory( const Tomahawk::result_ptr& );
static bool isIPWhitelisted( QHostAddress ip );
bool connectedToSession( const QString& session );
@ -129,10 +132,11 @@ public:
QList< StreamConnection* > streams() const { return m_scsessions; }
QSharedPointer< QIODevice > getIODeviceForUrl( const Tomahawk::result_ptr& result );
void registerIODeviceFactory( const QString &proto, boost::function< QSharedPointer< QIODevice >(Tomahawk::result_ptr) > fac );
QSharedPointer< QIODevice > localFileIODeviceFactory( const Tomahawk::result_ptr& result );
QSharedPointer< QIODevice > httpIODeviceFactory( const Tomahawk::result_ptr& result );
void getIODeviceForUrl( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
void registerIODeviceFactory( const QString &proto, IODeviceFactoryFunc fac );
void remoteIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
void localFileIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
void httpIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
bool isReady() const { return m_ready; };
@ -184,7 +188,7 @@ private:
QList< StreamConnection* > m_scsessions;
QMutex m_ftsession_mut;
QMap< QString,boost::function< QSharedPointer< QIODevice >(Tomahawk::result_ptr) > > m_iofactories;
QMap< QString, IODeviceFactoryFunc > m_iofactories;
QPointer< PortFwdThread > m_portfwd;
static Servent* s_instance;

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -19,10 +20,7 @@
#include "StreamConnection.h"
#include <QFile>
#include "Result.h"
#include "BufferIoDevice.h"
#include "network/ControlConnection.h"
#include "network/Servent.h"
@ -31,6 +29,10 @@
#include "SourceList.h"
#include "utils/Logger.h"
#include <boost/bind.hpp>
#include <QFile>
using namespace Tomahawk;
@ -179,8 +181,16 @@ StreamConnection::startSending( const Tomahawk::result_ptr& result )
m_result = result;
qDebug() << "Starting to transmit" << m_result->url();
QSharedPointer<QIODevice> io = Servent::instance()->getIODeviceForUrl( m_result );
if( !io )
boost::function< void ( QSharedPointer< QIODevice >& ) > callback =
boost::bind( &StreamConnection::reallyStartSending, this, result, _1 );
Servent::instance()->getIODeviceForUrl( m_result, callback );
}
void
StreamConnection::reallyStartSending( const Tomahawk::result_ptr& result, QSharedPointer< QIODevice >& io )
{
if( !io || io.isNull() )
{
qDebug() << "Couldn't read from source:" << m_result->url();
shutdown();

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -71,7 +72,8 @@ protected slots:
virtual void handleMsg( msg_ptr msg );
private slots:
void startSending( const Tomahawk::result_ptr& );
void startSending( const Tomahawk::result_ptr& result );
void reallyStartSending( const Tomahawk::result_ptr& result, QSharedPointer< QIODevice >& io ); //only called back from startSending
void sendSome();
void showStats( qint64 tx, qint64 rx );

View File

@ -293,7 +293,9 @@ QtScriptResolverHelper::md5( const QByteArray& input )
void
QtScriptResolverHelper::addCustomUrlHandler( const QString& protocol, const QString& callbackFuncName )
{
boost::function<QSharedPointer<QIODevice>(Tomahawk::result_ptr)> fac = boost::bind( &QtScriptResolverHelper::customIODeviceFactory, this, _1 );
boost::function< void( const Tomahawk::result_ptr&,
boost::function< void( QSharedPointer< QIODevice >& ) > )> fac =
boost::bind( &QtScriptResolverHelper::customIODeviceFactory, this, _1, _2 );
Servent::instance()->registerIODeviceFactory( protocol, fac );
m_urlCallback = callbackFuncName;
@ -314,22 +316,31 @@ QtScriptResolverHelper::base64Decode( const QByteArray& input )
}
QSharedPointer< QIODevice >
QtScriptResolverHelper::customIODeviceFactory( const Tomahawk::result_ptr& result )
void
QtScriptResolverHelper::customIODeviceFactory( const Tomahawk::result_ptr& result,
boost::function< void( QSharedPointer< QIODevice >& ) > callback )
{
QString getUrl = QString( "Tomahawk.resolver.instance.%1( '%2' );" ).arg( m_urlCallback )
.arg( QString( QUrl( result->url() ).toEncoded() ) );
QString urlStr = m_resolver->m_engine->mainFrame()->evaluateJavaScript( getUrl ).toString();
QSharedPointer< QIODevice > sp;
if ( urlStr.isEmpty() )
return QSharedPointer< QIODevice >();
{
callback( sp );
return;
}
QUrl url = QUrl::fromEncoded( urlStr.toUtf8() );
QNetworkRequest req( url );
tDebug() << "Creating a QNetowrkReply with url:" << req.url().toString();
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
return QSharedPointer<QIODevice>( reply, &QObject::deleteLater );
//boost::functions cannot accept temporaries as parameters
sp = QSharedPointer< QIODevice >( reply, &QObject::deleteLater );
callback( sp );
}

View File

@ -59,7 +59,8 @@ public:
Q_INVOKABLE QByteArray base64Encode( const QByteArray& input );
Q_INVOKABLE QByteArray base64Decode( const QByteArray& input );
QSharedPointer<QIODevice> customIODeviceFactory( const Tomahawk::result_ptr& result );
void customIODeviceFactory( const Tomahawk::result_ptr& result,
boost::function< void( QSharedPointer< QIODevice >& ) > callback ); // async
public slots:
QByteArray readRaw( const QString& fileName );

View File

@ -3,6 +3,7 @@
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -30,6 +31,8 @@
#include "Pipeline.h"
#include "Source.h"
#include <boost/bind.hpp>
#include <QHash>
@ -189,8 +192,16 @@ Api_v1::sid( QxtWebRequestEvent* event, QString unused )
return send404( event );
}
QSharedPointer<QIODevice> iodev = Servent::instance()->getIODeviceForUrl( rp );
if ( iodev.isNull() )
boost::function< void ( QSharedPointer< QIODevice >& ) > callback =
boost::bind( &Api_v1::processSid, this, event, rp, _1 );
Servent::instance()->getIODeviceForUrl( rp, callback );
}
void
Api_v1::processSid( QxtWebRequestEvent* event, Tomahawk::result_ptr& rp, QSharedPointer< QIODevice >& iodev )
{
if ( !iodev || iodev.isNull() )
{
return send404( event ); // 503?
}

View File

@ -2,6 +2,7 @@
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -36,6 +37,12 @@
#include <QSharedPointer>
#include <QStringList>
namespace Tomahawk
{
class Result;
typedef QSharedPointer< Result > result_ptr;
}
class Api_v1 : public QxtWebSlotService
{
Q_OBJECT
@ -70,6 +77,7 @@ public slots:
void index( QxtWebRequestEvent* event );
private:
void processSid( QxtWebRequestEvent* event, Tomahawk::result_ptr&, QSharedPointer< QIODevice >& );
QxtWebRequestEvent* m_storedEvent;
};