mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-01 11:50:37 +02:00
Merge pull request #207 from TheOneRing/snore-notify
added snorenotification support, this adds growl(on windows and mac), wi...
This commit is contained in:
@@ -332,6 +332,15 @@ if( WIN32 )
|
||||
macro_log_feature(QTSPARKLE_FOUND "qtsparkle" "Library for creating auto updaters written in Qt" "https://github.com/davidsansome/qtsparkle" FALSE "" "")
|
||||
endif( WIN32 )
|
||||
|
||||
if( WIN32 OR APPLE )
|
||||
if( TOMAHAWK_QT5 )
|
||||
macro_optional_find_package(LibsnoreQt5 QUIET)
|
||||
else()
|
||||
macro_optional_find_package(Libsnore QUIET)
|
||||
endif()
|
||||
macro_log_feature(LIBSNORE_FOUND "Libsnore" "Library for notifications" "https://github.com/TheOneRing/Snorenotify" FALSE "" "")
|
||||
endif()
|
||||
|
||||
#TODO: support external qxt
|
||||
set(QXTWEB_FOUND TRUE)
|
||||
set(QXTWEB_LIBRARIES qxtweb-standalone)
|
||||
|
@@ -2,6 +2,19 @@ include_directories(
|
||||
${ECHONEST_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIR}
|
||||
)
|
||||
if(WIN32 OR APPLE)
|
||||
if(BUILD_GUI AND LIBSNORE_FOUND)
|
||||
SET(snore_srcs
|
||||
snorenotify/SnoreNotifyPlugin.cpp
|
||||
)
|
||||
SET(SNORE_LINK_LIBRARIES ${LINK_LIBRARIES} ${LIBSNORE_LIBRARIES} )
|
||||
|
||||
tomahawk_add_plugin(snorenotify
|
||||
TYPE infoplugin EXPORT_MACRO INFOPLUGINDLLEXPORT_PRO
|
||||
SOURCES "${snore_srcs}" LINK_LIBRARIES "${SNORE_LINK_LIBRARIES}"
|
||||
)
|
||||
endif(BUILD_GUI AND LIBSNORE_FOUND)
|
||||
endif(WIN32 OR APPLE)
|
||||
|
||||
list(APPEND simple_plugins
|
||||
Echonest
|
||||
|
291
src/infoplugins/generic/snorenotify/SnoreNotifyPlugin.cpp
Normal file
291
src/infoplugins/generic/snorenotify/SnoreNotifyPlugin.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2013-2014, Patrick von Reth <vonreth@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.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
|
||||
* 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 "SnoreNotifyPlugin.h"
|
||||
|
||||
|
||||
#include "TomahawkSettings.h"
|
||||
|
||||
#include "utils/TomahawkUtils.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
|
||||
#include <snore/core/application.h>
|
||||
#include <snore/core/notification/icon.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QImage>
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
namespace Qt
|
||||
{
|
||||
inline QString escape( const QString &x )
|
||||
{
|
||||
return x.toHtmlEscaped();
|
||||
}
|
||||
}
|
||||
#else
|
||||
// QTextDocument provides Qt::escape()
|
||||
#include <QTextDocument>
|
||||
#endif
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
SnoreNotifyPlugin::SnoreNotifyPlugin()
|
||||
: InfoPlugin(),
|
||||
m_defaultIcon( RESPATH "icons/tomahawk-icon-512x512.png" )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped << InfoInboxReceived;
|
||||
|
||||
m_snore = new Snore::SnoreCore();
|
||||
m_snore->loadPlugins( Snore::SnorePlugin::BACKEND );
|
||||
QString backend = qgetenv( "SNORE_BACKEND" ).constData();
|
||||
|
||||
if( backend.isEmpty() )
|
||||
{
|
||||
m_snore->setPrimaryNotificationBackend();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_snore->setPrimaryNotificationBackend( backend ) )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Ivalid or unavailible Snore backend: " << backend << " availible backens: " << m_snore->notificationBackends();
|
||||
m_snore->setPrimaryNotificationBackend();
|
||||
}
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << m_snore->primaryNotificationBackend();
|
||||
|
||||
m_application = Snore::Application( qApp->applicationName(), m_defaultIcon );
|
||||
m_application.hints().setValue( "desktop-entry" ,"tomahawk" );
|
||||
|
||||
addAlert( InfoNotifyUser, tr( "Notify User" ) );
|
||||
addAlert( InfoNowPlaying, tr( "Now Playing" ) );
|
||||
addAlert( InfoTrackUnresolved, tr( "Unresolved track" ) );
|
||||
addAlert( InfoNowStopped, tr( "Playback Stopped" ) );
|
||||
addAlert( InfoInboxReceived, tr( "You received a Song recomondation" ) );
|
||||
|
||||
m_snore->registerApplication( m_application );
|
||||
|
||||
connect( m_snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
}
|
||||
|
||||
|
||||
SnoreNotifyPlugin::~SnoreNotifyPlugin()
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
|
||||
m_snore->deregisterApplication( m_application );
|
||||
m_snore->deleteLater();
|
||||
}
|
||||
|
||||
void
|
||||
SnoreNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "showing notification:" << TomahawkSettings::instance()->songChangeNotificationEnabled();
|
||||
if ( !TomahawkSettings::instance()->songChangeNotificationEnabled() )
|
||||
return;
|
||||
|
||||
if( m_snore->primaryNotificationBackend().isNull() )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "no notification backend set";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch ( pushData.type )
|
||||
{
|
||||
case Tomahawk::InfoSystem::InfoTrackUnresolved:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoTrackUnresolved,"The current track could not be resolved. Tomahawk will pick back up with the next resolvable track from this source." );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNotifyUser:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNotifyUser,pushData.infoPair.second.toString() );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowStopped:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNowStopped, "Tomahawk stopped playback." );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowPlaying:
|
||||
nowPlaying( pushData.infoPair.second );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoInboxReceived:
|
||||
inboxReceived( pushData.infoPair.second );
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
SnoreNotifyPlugin::slotActionInvoked( Snore::Notification n )
|
||||
{
|
||||
Q_UNUSED(n)
|
||||
TomahawkUtils::bringToFront();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SnoreNotifyPlugin::notifyUser( Tomahawk::InfoSystem::InfoType type, const QString& messageText, Snore::Icon icon )
|
||||
{
|
||||
if(!icon.isValid())
|
||||
{
|
||||
icon = m_defaultIcon;
|
||||
}
|
||||
const Snore::Alert &alert = m_alerts[ type ];
|
||||
Snore::Notification n( m_application , alert, alert.name(), messageText, icon );
|
||||
m_snore->broadcastNotification( n );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "showing notification:" << messageText;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
SnoreNotifyPlugin::addAlert( Tomahawk::InfoSystem::InfoType type, const QString &title )
|
||||
{
|
||||
Snore::Alert alert( title, m_defaultIcon );
|
||||
m_application.addAlert( alert );
|
||||
m_alerts[ type ] = alert;
|
||||
}
|
||||
|
||||
void
|
||||
SnoreNotifyPlugin::nowPlaying( const QVariant& input )
|
||||
{
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
if ( !input.canConvert< QVariantMap >() )
|
||||
return;
|
||||
|
||||
QVariantMap map = input.toMap();
|
||||
if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
return;
|
||||
|
||||
InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) )
|
||||
return;
|
||||
|
||||
QString messageText;
|
||||
// If the window manager supports notification styling then use it.
|
||||
if ( m_snore->primaryBackendSupportsRichtext() )
|
||||
{
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( "<br><i>%1</i> %2" ).arg( tr( "on", "'on' is followed by an album name" ) ).arg( Qt::escape( hash[ "album" ] ) );
|
||||
|
||||
messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( Qt::escape( hash[ "title" ] ) )
|
||||
.arg( Qt::escape( hash[ "artist" ] ) )
|
||||
.arg( album )
|
||||
.arg( QString( "<br><i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
}
|
||||
else
|
||||
{
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( " %1" ).arg( tr( "on \"%1\"", "%1 is an album name" ).arg( hash[ "album" ] ) );
|
||||
|
||||
messageText = tr( "\"%1\" by %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing" )
|
||||
.arg( hash[ "title" ] )
|
||||
.arg( hash[ "artist" ] )
|
||||
.arg( album );
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;
|
||||
|
||||
// If there is a cover availble use it, else use Tomahawk logo as default.
|
||||
Snore::Icon image;
|
||||
if ( map.contains( "cover" ) && map[ "cover" ].canConvert< QImage >() )
|
||||
{
|
||||
image = Snore::Icon( map[ "cover" ].value< QImage >() );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << image;
|
||||
}
|
||||
notifyUser( InfoNowPlaying, messageText, image );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
SnoreNotifyPlugin::inboxReceived( const QVariant& input )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
if ( !input.canConvert< QVariantMap >() )
|
||||
return;
|
||||
|
||||
QVariantMap map = input.toMap();
|
||||
|
||||
if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
return;
|
||||
if ( !map.contains( "sourceinfo" ) || !map[ "sourceinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
return;
|
||||
|
||||
InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) )
|
||||
return;
|
||||
|
||||
InfoStringHash src = map[ "sourceinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !src.contains( "friendlyname" ) )
|
||||
return;
|
||||
|
||||
QString messageText;
|
||||
// If the window manager supports notification styling then use it.
|
||||
if ( m_snore->primaryBackendSupportsRichtext() )
|
||||
{
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( Qt::escape( src["friendlyname"] ) )
|
||||
.arg( Qt::escape( hash[ "title" ] ) )
|
||||
.arg( Qt::escape( hash[ "artist" ] ) )
|
||||
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
}
|
||||
else
|
||||
{
|
||||
messageText = tr( "%1 sent you \"%2\" by %3.", "%1 is a nickname, %2 is a title, %3 is an artist" )
|
||||
.arg( src["friendlyname"] )
|
||||
.arg( hash[ "title" ] )
|
||||
.arg( hash[ "artist" ] );
|
||||
}
|
||||
|
||||
Snore::Icon icon( RESPATH "images/inbox-512x512.png" );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNowPlaying, messageText, icon );
|
||||
}
|
||||
|
||||
|
||||
} //ns InfoSystem
|
||||
|
||||
} //ns Tomahawk
|
||||
|
||||
Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::SnoreNotifyPlugin )
|
81
src/infoplugins/generic/snorenotify/SnoreNotifyPlugin.h
Normal file
81
src/infoplugins/generic/snorenotify/SnoreNotifyPlugin.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2013-2014, Patrick von Reth <vonreth@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.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
|
||||
* 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 SNORENOTIFYPLUGIN_H
|
||||
#define SNORENOTIFYPLUGIN_H
|
||||
|
||||
#include "../../InfoPluginDllMacro.h"
|
||||
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include <snore/core/snore.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class INFOPLUGINDLLEXPORT SnoreNotifyPlugin : public InfoPlugin
|
||||
{
|
||||
Q_PLUGIN_METADATA( IID "org.tomahawk-player.Player.InfoPlugin" )
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
|
||||
|
||||
public:
|
||||
SnoreNotifyPlugin();
|
||||
virtual ~SnoreNotifyPlugin();
|
||||
|
||||
|
||||
protected slots:
|
||||
virtual void init() {}
|
||||
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
|
||||
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
protected slots:
|
||||
void slotActionInvoked(Snore::Notification n);
|
||||
|
||||
private:
|
||||
void notifyUser( InfoType type, const QString &messageText, Snore::Icon icon = Snore::Icon() );
|
||||
void addAlert( Tomahawk::InfoSystem::InfoType type, const QString &title );
|
||||
Snore::SnoreCore *m_snore;
|
||||
Snore::Application m_application;
|
||||
Snore::Icon m_defaultIcon;
|
||||
QHash< Tomahawk::InfoSystem::InfoType, Snore::Alert > m_alerts;
|
||||
|
||||
void nowPlaying( const QVariant &input );
|
||||
void inboxReceived( const QVariant &input );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SNORENOTIFYPLUGIN_H
|
Reference in New Issue
Block a user