mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 19:30:21 +02:00
Use getStreamUrl on ResultProviders instead of awkward custom iodevicefactories
This commit is contained in:
@@ -271,17 +271,6 @@ Tomahawk.Resolver = {
|
||||
getStreamUrl: function (params) {
|
||||
return params;
|
||||
},
|
||||
|
||||
_convertUrls: function (results) {
|
||||
var that = this;
|
||||
return results.map(function (r) {
|
||||
if (r && r.url) {
|
||||
r.url = that._urlProtocol + '://' + r.url;
|
||||
}
|
||||
return r;
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_resolve: function (params) {
|
||||
var that = this;
|
||||
var collectionPromises = [];
|
||||
@@ -297,26 +286,12 @@ Tomahawk.Resolver = {
|
||||
}).then(function (collectionResults) {
|
||||
return RSVP.Promise.resolve(that.resolve(params)).then(function (results) {
|
||||
return {
|
||||
'results': that._convertUrls(results.concat(collectionResults))
|
||||
'results': results.concat(collectionResults)
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_init: function () {
|
||||
this._urlProtocol = this.settings.name.replace(/[^a-zA-Z]/g, '').toLowerCase();
|
||||
Tomahawk.addCustomUrlHandler(this._urlProtocol, '_adapter_getStreamUrl', true);
|
||||
Tomahawk.log('Registered custom url handler for protocol "' + this._urlProtocol + '"');
|
||||
this.init();
|
||||
},
|
||||
|
||||
_adapter_getStreamUrl: function (params) {
|
||||
params.url = params.url.slice(this._urlProtocol.length + 3);
|
||||
RSVP.Promise.resolve(this.getStreamUrl(params)).then(function (result) {
|
||||
Tomahawk.reportStreamUrl(params.qid, result.url, result.headers);
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_search: function (params) {
|
||||
var that = this;
|
||||
var collectionPromises = [];
|
||||
@@ -331,7 +306,7 @@ Tomahawk.Resolver = {
|
||||
}).then(function (collectionResults) {
|
||||
return RSVP.Promise.resolve(that.search(params)).then(function (results) {
|
||||
return {
|
||||
'results': that._convertUrls(results.concat(collectionResults))
|
||||
'results': results.concat(collectionResults)
|
||||
};
|
||||
});
|
||||
});
|
||||
@@ -1713,7 +1688,7 @@ Tomahawk.Collection = {
|
||||
);
|
||||
return t.execDeferredStatements();
|
||||
}).then(function (results) {
|
||||
return {results: Tomahawk.resolver.instance._convertUrls(results[0])};
|
||||
return {results: results[0]};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1887,6 +1862,14 @@ Tomahawk.Collection = {
|
||||
Tomahawk.Collection.BrowseCapability.Albums,
|
||||
Tomahawk.Collection.BrowseCapability.Tracks];
|
||||
return this.settings;
|
||||
},
|
||||
|
||||
getStreamUrl: function(params) {
|
||||
if(this.resolver) {
|
||||
return this.resolver.getStreamUrl(params);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1910,14 +1893,6 @@ Tomahawk.addTrackResults = function (result) {
|
||||
delete Tomahawk.PluginManager.resolve[result.qid];
|
||||
};
|
||||
|
||||
Tomahawk.reportStreamUrl = function (qid, streamUrl, headers) {
|
||||
Tomahawk.PluginManager.resolve[qid]({
|
||||
url: streamUrl,
|
||||
headers: headers
|
||||
});
|
||||
delete Tomahawk.PluginManager.resolve[qid];
|
||||
};
|
||||
|
||||
Tomahawk.addUrlResult = function (url, result) {
|
||||
/* Merge the whole mess into one consistent result which is independent of type
|
||||
var cleanResult = {
|
||||
|
@@ -30,11 +30,8 @@ ResultProvider::~ResultProvider()
|
||||
ScriptJob*
|
||||
ResultProvider::getStreamUrl( const result_ptr& result )
|
||||
{
|
||||
QUrl url = result->url();
|
||||
|
||||
QVariantMap data;
|
||||
data[ "result" ] = QVariant::fromValue( result );
|
||||
data[ "url" ] = url;
|
||||
data[ "url" ] = result->url();
|
||||
|
||||
return new SyncScriptJob( data );
|
||||
}
|
||||
|
@@ -32,6 +32,8 @@
|
||||
#include "playlist/SingleTrackPlaylistInterface.h"
|
||||
#include "utils/Closure.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/NetworkReply.h"
|
||||
#include "utils/NetworkAccessManager.h"
|
||||
|
||||
#include "Album.h"
|
||||
#include "Artist.h"
|
||||
@@ -577,27 +579,62 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
|
||||
ScriptJob* job = result->resolvedBy()->getStreamUrl( result );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( gotStreamUrl( QVariantMap ) ) );
|
||||
job->setProperty( "result", QVariant::fromValue( result ) );
|
||||
job->start();
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
{
|
||||
QString url = data[ "url" ].toString();
|
||||
result_ptr result = data[ "result" ].value<result_ptr>();
|
||||
QString streamUrl = data[ "url" ].toString();
|
||||
QVariantMap headers = data[ "headers" ].toMap();
|
||||
Tomahawk::result_ptr result = sender()->property( "result" ).value<result_ptr>();
|
||||
|
||||
if ( !TomahawkUtils::isLocalResult( url ) && !TomahawkUtils::isHttpResult( url )
|
||||
&& !TomahawkUtils::isRtmpResult( url ) )
|
||||
if ( streamUrl.isEmpty() || !( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) || TomahawkUtils::isRtmpResult( streamUrl ) ) )
|
||||
{
|
||||
performLoadIODevice( result, url );
|
||||
// Not an http(s) or RTMP URL, get IO device
|
||||
QSharedPointer< QIODevice > sp;
|
||||
performLoadIODevice( result, streamUrl );
|
||||
}
|
||||
else
|
||||
{
|
||||
QSharedPointer< QIODevice > io;
|
||||
performLoadTrack( result, result->url(), io );
|
||||
// TODO: just make this part of the http(s) IoDeviceFactory (?)
|
||||
QUrl url = QUrl::fromEncoded( streamUrl.toUtf8() );
|
||||
QNetworkRequest req( url );
|
||||
|
||||
QMap<QString, QString> parsedHeaders;
|
||||
foreach ( const QString& key, headers.keys() )
|
||||
{
|
||||
Q_ASSERT_X( headers[key].canConvert( QVariant::String ), Q_FUNC_INFO, "Expected a Map of string for additional headers" );
|
||||
if ( headers[key].canConvert( QVariant::String ) )
|
||||
{
|
||||
parsedHeaders.insert( key, headers[key].toString() );
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( const QString& key, parsedHeaders.keys() )
|
||||
{
|
||||
req.setRawHeader( key.toLatin1(), parsedHeaders[key].toLatin1() );
|
||||
}
|
||||
|
||||
tDebug() << "Creating a QNetworkReply with url:" << req.url().toString();
|
||||
NetworkReply* reply = new NetworkReply( Tomahawk::Utils::nam()->get( req ) );
|
||||
NewClosure( reply, SIGNAL( finalUrlReached() ), this, SLOT( gotRedirectedStreamUrl( Tomahawk::result_ptr, NetworkReply* )), result, reply );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply )
|
||||
{
|
||||
// std::functions cannot accept temporaries as parameters
|
||||
QSharedPointer< QIODevice > sp ( reply->reply(), &QObject::deleteLater );
|
||||
QString url = reply->reply()->url().toString();
|
||||
reply->disconnectFromReply();
|
||||
reply->deleteLater();
|
||||
|
||||
performLoadTrack( result, url, sp );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::onPositionChanged( float new_position )
|
||||
|
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class NetworkReply;
|
||||
class AudioEnginePrivate;
|
||||
|
||||
class DLLEXPORT AudioEngine : public QObject
|
||||
@@ -181,6 +182,9 @@ signals:
|
||||
private slots:
|
||||
void loadTrack( const Tomahawk::result_ptr& result ); //async!
|
||||
void gotStreamUrl( const QVariantMap& data );
|
||||
void gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply );
|
||||
|
||||
|
||||
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url ); //only call from loadTrack kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void loadPreviousTrack();
|
||||
|
@@ -538,12 +538,6 @@ JSResolver::error() const
|
||||
void
|
||||
JSResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "resolve", Qt::QueuedConnection, Q_ARG(Tomahawk::query_ptr, query) );
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptJob* job = nullptr;
|
||||
if ( !query->isFullTextQuery() )
|
||||
{
|
||||
@@ -746,3 +740,13 @@ JSResolver::instanceUUID()
|
||||
{
|
||||
return Tomahawk::Database::instance()->impl()->dbid();
|
||||
}
|
||||
|
||||
|
||||
ScriptJob*
|
||||
JSResolver::getStreamUrl( const result_ptr& result )
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["url"] = result->url();
|
||||
|
||||
return scriptObject()->invoke( "getStreamUrl", arguments );
|
||||
}
|
||||
|
@@ -75,6 +75,8 @@ public:
|
||||
|
||||
ScriptAccount* scriptAccount() const;
|
||||
|
||||
ScriptJob* getStreamUrl( const result_ptr& result ) override;
|
||||
|
||||
public slots:
|
||||
void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
void stop() override;
|
||||
|
@@ -72,7 +72,6 @@ JSResolverHelper::JSResolverHelper( const QString& scriptPath, JSResolver* paren
|
||||
: QObject( parent )
|
||||
, m_resolver( parent )
|
||||
, m_scriptPath( scriptPath )
|
||||
, m_urlCallbackIsAsync( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -480,31 +479,6 @@ JSResolverHelper::accountId()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::addCustomUrlHandler( const QString& protocol,
|
||||
const QString& callbackFuncName,
|
||||
const QString& isAsynchronous )
|
||||
{
|
||||
m_urlCallbackIsAsync = ( isAsynchronous.toLower() == "true" );
|
||||
|
||||
std::function< void( const Tomahawk::result_ptr&, const QString&,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > )> fac =
|
||||
std::bind( &JSResolverHelper::customIODeviceFactory, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3 );
|
||||
Tomahawk::UrlHandler::registerIODeviceFactory( protocol, fac );
|
||||
|
||||
m_urlCallback = callbackFuncName;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::reportStreamUrl( const QString& qid, const QString& streamUrl )
|
||||
{
|
||||
reportStreamUrl( qid, streamUrl, QVariantMap() );
|
||||
}
|
||||
|
||||
|
||||
void JSResolverHelper::nativeAssert( bool assertion, const QString& message )
|
||||
{
|
||||
if ( !assertion )
|
||||
@@ -515,61 +489,6 @@ void JSResolverHelper::nativeAssert( bool assertion, const QString& message )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::customIODeviceFactory( const Tomahawk::result_ptr&, const QString& url,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback )
|
||||
{
|
||||
//can be sync or async
|
||||
if ( m_urlCallbackIsAsync )
|
||||
{
|
||||
QString qid = uuid();
|
||||
QString getUrl = QString(
|
||||
"if(Tomahawk.resolver.instance['_adapter_%1']) {"
|
||||
" Tomahawk.resolver.instance._adapter_%1( {qid: '%2', url: '%3'} );"
|
||||
"} else {"
|
||||
" Tomahawk.resolver.instance.%1( {qid: '%2', url: '%3'} );"
|
||||
"}"
|
||||
).arg( m_urlCallback )
|
||||
.arg( qid )
|
||||
.arg( url );
|
||||
|
||||
m_streamCallbacks.insert( qid, callback );
|
||||
m_resolver->d_func()->scriptAccount->evaluateJavaScript( getUrl );
|
||||
}
|
||||
else
|
||||
{
|
||||
QString getUrl = QString( "Tomahawk.resolver.instance.%1( '%2' );" ).arg( m_urlCallback )
|
||||
.arg( url );
|
||||
|
||||
QString urlStr = m_resolver->d_func()->scriptAccount->evaluateJavaScriptWithResult( getUrl ).toString();
|
||||
|
||||
returnStreamUrl( urlStr, QMap<QString, QString>(), callback );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::reportStreamUrl( const QString& qid, const QString& streamUrl, const QVariantMap& headers )
|
||||
{
|
||||
if ( !m_streamCallbacks.contains( qid ) )
|
||||
return;
|
||||
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback = m_streamCallbacks.take( qid );
|
||||
|
||||
QMap<QString, QString> parsedHeaders;
|
||||
foreach ( const QString& key, headers.keys() )
|
||||
{
|
||||
Q_ASSERT_X( headers[key].canConvert( QVariant::String ), Q_FUNC_INFO, "Expected a Map of string for additional headers" );
|
||||
if ( headers[key].canConvert( QVariant::String ) )
|
||||
{
|
||||
parsedHeaders.insert( key, headers[key].toString() );
|
||||
}
|
||||
}
|
||||
|
||||
returnStreamUrl( streamUrl, parsedHeaders, callback );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::nativeRetrieveMetadata( int metadataId, const QString& url,
|
||||
const QString& mime_type, int sizehint,
|
||||
@@ -955,43 +874,3 @@ JSResolverHelper::readdResolver()
|
||||
Pipeline::instance()->addResolver( m_resolver );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::returnStreamUrl( const QString& streamUrl, const QMap<QString, QString>& headers,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback )
|
||||
{
|
||||
if ( streamUrl.isEmpty() || !( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
|
||||
{
|
||||
// Not an https? URL, so let Phonon handle it
|
||||
QSharedPointer< QIODevice > sp;
|
||||
callback( streamUrl, sp );
|
||||
}
|
||||
else
|
||||
{
|
||||
QUrl url = QUrl::fromEncoded( streamUrl.toUtf8() );
|
||||
QNetworkRequest req( url );
|
||||
foreach ( const QString& key, headers.keys() )
|
||||
{
|
||||
req.setRawHeader( key.toLatin1(), headers[key].toLatin1() );
|
||||
}
|
||||
tDebug() << "Creating a QNetworkReply with url:" << req.url().toString();
|
||||
NetworkReply* reply = new NetworkReply( Tomahawk::Utils::nam()->get( req ) );
|
||||
|
||||
NewClosure( reply, SIGNAL( finalUrlReached() ), this, SLOT( gotStreamUrl( IODeviceCallback, NetworkReply* )), callback, reply );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE( IODeviceCallback )
|
||||
|
||||
void
|
||||
JSResolverHelper::gotStreamUrl( std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback, NetworkReply* reply )
|
||||
{
|
||||
// std::functions cannot accept temporaries as parameters
|
||||
QSharedPointer< QIODevice > sp ( reply->reply(), &QObject::deleteLater );
|
||||
QString url = reply->reply()->url().toString();
|
||||
reply->disconnectFromReply();
|
||||
reply->deleteLater();
|
||||
|
||||
callback( url, sp );
|
||||
}
|
||||
|
@@ -61,9 +61,6 @@ public:
|
||||
*/
|
||||
Q_INVOKABLE QString accountId();
|
||||
|
||||
Q_INVOKABLE void addCustomUrlHandler( const QString& protocol, const QString& callbackFuncName, const QString& isAsynchronous = "false" );
|
||||
Q_INVOKABLE void reportStreamUrl( const QString& qid, const QString& streamUrl );
|
||||
Q_INVOKABLE void reportStreamUrl( const QString& qid, const QString& streamUrl, const QVariantMap& headers );
|
||||
|
||||
/**
|
||||
* Make Tomahawk assert the assertion is true, probably not to be used by resolvers directly
|
||||
@@ -122,13 +119,6 @@ public:
|
||||
Q_INVOKABLE void readdResolver();
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL USE ONLY!
|
||||
*/
|
||||
void customIODeviceFactory( const Tomahawk::result_ptr&, const QString& url,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback ); // async
|
||||
|
||||
|
||||
public slots:
|
||||
QByteArray readRaw( const QString& fileName );
|
||||
QString readBase64( const QString& fileName );
|
||||
@@ -149,22 +139,15 @@ public slots:
|
||||
void unregisterScriptPlugin( const QString& type, const QString& objectId );
|
||||
|
||||
private slots:
|
||||
void gotStreamUrl( IODeviceCallback callback, NetworkReply* reply );
|
||||
void nativeAsyncRequestDone( int requestId, NetworkReply* reply );
|
||||
|
||||
private:
|
||||
void returnStreamUrl( const QString& streamUrl, const QMap<QString, QString>& headers,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback );
|
||||
|
||||
bool indexDataFromVariant( const QVariantMap& map, struct Tomahawk::IndexData& indexData );
|
||||
QVariantList searchInFuzzyIndex( const Tomahawk::query_ptr& query );
|
||||
|
||||
QVariantMap m_resolverConfig;
|
||||
JSResolver* m_resolver;
|
||||
QString m_scriptPath, m_urlCallback, m_urlTranslator;
|
||||
QHash< QString, std::function< void( const QString&, QSharedPointer< QIODevice >& ) > > m_streamCallbacks;
|
||||
QHash< QString, std::function< void( const QString& ) > > m_translatorCallbacks;
|
||||
bool m_urlCallbackIsAsync;
|
||||
QString m_scriptPath;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "resolvers/ScriptCommand_AllAlbums.h"
|
||||
#include "resolvers/ScriptCommand_AllTracks.h"
|
||||
#include "ScriptAccount.h"
|
||||
#include "Result.h"
|
||||
|
||||
#include <QImageReader>
|
||||
#include <QPainter>
|
||||
@@ -223,6 +224,15 @@ void ScriptCollection::parseMetaData()
|
||||
return parseMetaData( readMetaData() );
|
||||
}
|
||||
|
||||
ScriptJob*
|
||||
ScriptCollection::getStreamUrl( const result_ptr& result )
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["url"] = result->url();
|
||||
|
||||
return scriptObject()->invoke( "getStreamUrl", arguments );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptCollection::parseMetaData( const QVariantMap& metadata )
|
||||
|
@@ -91,6 +91,8 @@ public:
|
||||
void parseMetaData();
|
||||
void parseMetaData( const QVariantMap& metadata );
|
||||
|
||||
ScriptJob* getStreamUrl( const result_ptr& result ) override;
|
||||
|
||||
private slots:
|
||||
void onIconFetched();
|
||||
|
||||
|
Reference in New Issue
Block a user