mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-20 07:49:42 +01:00
Merge pull request #220 from tomahawk-player/webapi-1.5
Add basic remote control API
This commit is contained in:
commit
0f175bcc37
@ -28,6 +28,7 @@
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/TomahawkUtils.h"
|
||||
|
||||
#include "Api_v1_5.h"
|
||||
#include "Pipeline.h"
|
||||
#include "Result.h"
|
||||
#include "Source.h"
|
||||
@ -41,9 +42,15 @@ using namespace TomahawkUtils;
|
||||
|
||||
Api_v1::Api_v1( QxtAbstractWebSessionManager* sm, QObject* parent )
|
||||
: QxtWebSlotService(sm, parent)
|
||||
, m_api_v1_5( new Api_v1_5( this ) )
|
||||
{
|
||||
}
|
||||
|
||||
Api_v1::~Api_v1()
|
||||
{
|
||||
delete m_api_v1_5;
|
||||
}
|
||||
|
||||
void
|
||||
Api_v1::auth_1( QxtWebRequestEvent* event, QString arg )
|
||||
{
|
||||
@ -155,23 +162,67 @@ Api_v1::auth_2( QxtWebRequestEvent* event, QString arg )
|
||||
}
|
||||
|
||||
|
||||
// all v1 api calls go to /api/
|
||||
/**
|
||||
* Handle API calls.
|
||||
*
|
||||
* All v1.0 API (standard Playdar) calls go to /api/?method=
|
||||
* All v1.5 API (simple remote control) calls go to /api/1.5/
|
||||
*/
|
||||
void
|
||||
Api_v1::api( QxtWebRequestEvent* event )
|
||||
Api_v1::api( QxtWebRequestEvent* event, const QString& version, const QString& method, const QString& arg1, const QString& arg2, const QString& arg3 )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << "HTTP" << event->url.toString();
|
||||
|
||||
const QUrl& url = event->url;
|
||||
if ( urlHasQueryItem( url, "method" ) )
|
||||
{
|
||||
const QString method = urlQueryItemValue( url, "method" );
|
||||
if ( version.isEmpty() ) {
|
||||
// We dealing with API 1.0
|
||||
|
||||
if ( method == "stat" ) return stat( event );
|
||||
if ( method == "resolve" ) return resolve( event );
|
||||
if ( method == "get_results" ) return get_results( event );
|
||||
const QUrl& url = event->url;
|
||||
if ( urlHasQueryItem( url, "method" ) )
|
||||
{
|
||||
const QString method = urlQueryItemValue( url, "method" );
|
||||
|
||||
if ( method == "stat" ) return stat( event );
|
||||
if ( method == "resolve" ) return resolve( event );
|
||||
if ( method == "get_results" ) return get_results( event );
|
||||
}
|
||||
|
||||
send404( event );
|
||||
}
|
||||
else if ( version == "1.5" )
|
||||
{
|
||||
if ( !arg3.isEmpty() )
|
||||
{
|
||||
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ), Q_ARG( QString, arg1 ), Q_ARG( QString, arg2 ), Q_ARG( QString, arg3 ) ) )
|
||||
{
|
||||
apiCallFailed(event, method);
|
||||
}
|
||||
}
|
||||
else if ( !arg2.isEmpty() )
|
||||
{
|
||||
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ), Q_ARG( QString, arg1 ), Q_ARG( QString, arg2 ) ) )
|
||||
{
|
||||
apiCallFailed(event, method);
|
||||
}
|
||||
}
|
||||
else if ( !arg1.isEmpty() )
|
||||
{
|
||||
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ), Q_ARG( QString, arg1 ) ) )
|
||||
{
|
||||
apiCallFailed(event, method);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ) ) )
|
||||
{
|
||||
apiCallFailed(event, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sendPlain404( event, QString( "Unknown API version %1" ).arg( version ), "API version not found" );
|
||||
}
|
||||
|
||||
send404( event );
|
||||
}
|
||||
|
||||
|
||||
@ -226,6 +277,16 @@ Api_v1::send404( QxtWebRequestEvent* event )
|
||||
postEvent( wpe );
|
||||
}
|
||||
|
||||
void
|
||||
Api_v1::sendPlain404( QxtWebRequestEvent* event, const QString& message, const QString& statusmessage )
|
||||
{
|
||||
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, message.toUtf8() );
|
||||
e->contentType = "text/plain";
|
||||
e->status = 404;
|
||||
e->statusMessage = statusmessage.toLatin1().constData();
|
||||
postEvent( e );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Api_v1::stat( QxtWebRequestEvent* event )
|
||||
@ -411,6 +472,7 @@ Api_v1::sendJSON( const QVariantMap& m, QxtWebRequestEvent* event )
|
||||
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, body );
|
||||
e->contentType = ctype;
|
||||
e->headers.insert( "Content-Length", QString::number( body.length() ) );
|
||||
e->headers.insert( "Access-Control-Allow-Origin", "*" );
|
||||
postEvent( e );
|
||||
tDebug( LOGVERBOSE ) << "JSON response" << event->url.toString() << body;
|
||||
}
|
||||
@ -447,3 +509,30 @@ Api_v1::index( QxtWebRequestEvent* event )
|
||||
{
|
||||
send404( event );
|
||||
}
|
||||
|
||||
void
|
||||
Api_v1::apiCallFailed( QxtWebRequestEvent* event, const QString& method )
|
||||
{
|
||||
sendPlain404( event, QString( "Method \"%1\" for API 1.5 not found" ).arg( method ), "Method in API 1.5 not found" );
|
||||
}
|
||||
|
||||
void
|
||||
Api_v1::sendJsonOk( QxtWebRequestEvent* event )
|
||||
{
|
||||
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, "{ result: \"ok\" }" );
|
||||
e->headers.insert( "Access-Control-Allow-Origin", "*" );
|
||||
e->contentType = "application/json";
|
||||
postEvent( e );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Api_v1::sendJsonError( QxtWebRequestEvent* event, const QString& message )
|
||||
{
|
||||
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, QString( "{ result: \"error\", error: \"%1\" }" ).arg( message ).toUtf8().constData() );
|
||||
e->headers.insert( "Access-Control-Allow-Origin", "*" );
|
||||
e->contentType = "application/json";
|
||||
e->status = 500;
|
||||
e->statusMessage = "Method call failed.";
|
||||
postEvent( e );
|
||||
}
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QStringList>
|
||||
|
||||
class Api_v1_5;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
class Result;
|
||||
@ -51,6 +53,7 @@ Q_OBJECT
|
||||
|
||||
public:
|
||||
Api_v1( QxtAbstractWebSessionManager* sm, QObject* parent = 0 );
|
||||
virtual ~Api_v1();
|
||||
|
||||
public slots:
|
||||
// authenticating uses /auth_1
|
||||
@ -59,7 +62,12 @@ public slots:
|
||||
void auth_2( QxtWebRequestEvent* event, QString unused = QString() );
|
||||
|
||||
// all v1 api calls go to /api/
|
||||
void api( QxtWebRequestEvent* event );
|
||||
void api( QxtWebRequestEvent* event,
|
||||
const QString& version = QString(),
|
||||
const QString& method = QString(),
|
||||
const QString& arg1 = QString(),
|
||||
const QString& arg2 = QString(),
|
||||
const QString& arg3 = QString() );
|
||||
|
||||
// request for stream: /sid/<id>
|
||||
void sid( QxtWebRequestEvent* event, QString unused = QString() );
|
||||
@ -74,15 +82,22 @@ public slots:
|
||||
|
||||
// load an html template from a file, replace args from map
|
||||
// then serve
|
||||
void sendJsonError( QxtWebRequestEvent* event, const QString& message );
|
||||
void sendJsonOk( QxtWebRequestEvent* event );
|
||||
void sendWebpageWithArgs( QxtWebRequestEvent* event, const QString& filenameSource, const QHash< QString, QString >& args );
|
||||
|
||||
void index( QxtWebRequestEvent* event );
|
||||
|
||||
protected:
|
||||
void apiCallFailed( QxtWebRequestEvent* event, const QString& method );
|
||||
void sendPlain404( QxtWebRequestEvent* event, const QString& message, const QString& statusmessage );
|
||||
|
||||
private:
|
||||
void processSid( QxtWebRequestEvent* event, Tomahawk::result_ptr&, QSharedPointer< QIODevice >& );
|
||||
|
||||
QxtWebRequestEvent* m_storedEvent;
|
||||
QSharedPointer< QIODevice > m_ioDevice;
|
||||
Api_v1_5* m_api_v1_5;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
100
src/libtomahawk-playdarapi/Api_v1_5.cpp
Normal file
100
src/libtomahawk-playdarapi/Api_v1_5.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Uwe L. Korn <uwelk@xhochy.com>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Api_v1_5.h"
|
||||
|
||||
#include "Api_v1.h"
|
||||
|
||||
#include "audio/AudioEngine.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
// Assumptions: QxtWebRequestEvent instance is called event and result is true on success
|
||||
#define JSON_REPLY( result, message ) jsonReply( event, Q_FUNC_INFO, message, !result )
|
||||
|
||||
|
||||
Api_v1_5::Api_v1_5( Api_v1* parent )
|
||||
: QObject( parent )
|
||||
, m_service( parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Api_v1_5::ping( QxtWebRequestEvent* event )
|
||||
{
|
||||
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, "pong" );
|
||||
e->headers.insert( "Access-Control-Allow-Origin", "*" );
|
||||
e->contentType = "text/plain";
|
||||
m_service->postEvent( e );
|
||||
}
|
||||
|
||||
void
|
||||
Api_v1_5::playback( QxtWebRequestEvent* event, const QString& command )
|
||||
{
|
||||
if ( command == "next")
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "next", Qt::QueuedConnection ) , "Skipping to the next track failed." );
|
||||
}
|
||||
else if ( command == "previous" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "previous", Qt::QueuedConnection ), "Rewinding to the previous track failed." );
|
||||
}
|
||||
else if ( command == "playpause" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "playPause", Qt::QueuedConnection ), "Play/Pause failed." );
|
||||
}
|
||||
else if ( command == "play" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "play", Qt::QueuedConnection ), "Starting the playback failed." );
|
||||
}
|
||||
else if ( command == "pause" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "pause", Qt::QueuedConnection ), "Pausing the current track failed." );
|
||||
}
|
||||
else if ( command == "stop" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "stop", Qt::QueuedConnection ), "Stopping the current track failed." );
|
||||
}
|
||||
else if ( command == "lowervolume" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "lowerVolume", Qt::QueuedConnection ), "Lowering volume failed." );
|
||||
}
|
||||
else if ( command == "raisevolume" )
|
||||
{
|
||||
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "raiseVolume", Qt::QueuedConnection ), "Raising volume failed." );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_service->sendJsonError( event, "No such playback command." );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Api_v1_5::jsonReply( QxtWebRequestEvent* event, const char* funcInfo, const QString& errorMessage, bool isError )
|
||||
{
|
||||
if ( isError )
|
||||
{
|
||||
tLog( LOGVERBOSE ) << funcInfo << errorMessage;
|
||||
m_service->sendJsonError( event, errorMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_service->sendJsonOk( event );
|
||||
}
|
||||
}
|
||||
|
55
src/libtomahawk-playdarapi/Api_v1_5.h
Normal file
55
src/libtomahawk-playdarapi/Api_v1_5.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2014, Uwe L. Korn <uwelk@xhochy.com>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef API_V1_5_H
|
||||
#define API_V1_5_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Api_v1;
|
||||
class QxtWebRequestEvent;
|
||||
|
||||
class Api_v1_5 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Api_v1_5( Api_v1* parent = 0 );
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Simple test to check for API 1.5 support.
|
||||
*
|
||||
* This call needs no authentication.
|
||||
*/
|
||||
void ping( QxtWebRequestEvent* event );
|
||||
|
||||
/**
|
||||
* Control playback.
|
||||
*/
|
||||
void playback( QxtWebRequestEvent* event, const QString& command );
|
||||
|
||||
protected:
|
||||
void jsonReply( QxtWebRequestEvent* event, const char* funcInfo, const QString& errorMessage, bool isError );
|
||||
|
||||
private:
|
||||
Api_v1* m_service;
|
||||
};
|
||||
|
||||
#endif // API_V1_5_H
|
@ -3,6 +3,7 @@ set(TOMAHAWK_PLAYDARAPI_LIBRARY_TARGET tomahawk-playdarapi)
|
||||
|
||||
list(APPEND ${TOMAHAWK_PLAYDARAPI_LIBRARY_TARGET}_SOURCES
|
||||
Api_v1.cpp
|
||||
Api_v1_5.cpp
|
||||
PlaydarApi.cpp
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user