Use virtual functions for OSD

This commit is contained in:
Jonas Kvinge 2020-08-09 01:37:00 +02:00
parent 184e9a5c93
commit ab7d383cf1
18 changed files with 281 additions and 198 deletions

10
debian/copyright vendored
View File

@ -122,8 +122,14 @@ Files: src/core/main.cpp
src/context/contextalbumsview.h
src/widgets/playingwidget.cpp
src/widgets/playingwidget.h
src/widgets/osdpretty.cpp
src/widgets/osdpretty.h
src/osd/osdbase.cpp
src/osd/osdbase.h
src/osd/osdpretty.cpp
src/osd/osdpretty.h
src/osd/osddbus.cpp
src/osd/osddbus.h
src/osd/osdmac.cpp
src/osd/osdmac.h
src/dialogs/about.cpp
src/dialogs/about.h
src/playlist/playlist.cpp

View File

@ -184,8 +184,6 @@ set(SOURCES
widgets/linetextedit.cpp
widgets/multiloadingindicator.cpp
widgets/playingwidget.cpp
widgets/osd.cpp
widgets/osdpretty.cpp
widgets/renametablineedit.cpp
widgets/volumeslider.cpp
widgets/stickyslider.cpp
@ -195,6 +193,9 @@ set(SOURCES
widgets/tracksliderslider.cpp
widgets/loginstatewidget.cpp
osd/osdbase.cpp
osd/osdpretty.cpp
musicbrainz/acoustidclient.cpp
musicbrainz/musicbrainzclient.cpp
@ -380,8 +381,6 @@ set(HEADERS
widgets/linetextedit.h
widgets/multiloadingindicator.h
widgets/playingwidget.h
widgets/osd.h
widgets/osdpretty.h
widgets/renametablineedit.h
widgets/volumeslider.h
widgets/stickyslider.h
@ -392,6 +391,9 @@ set(HEADERS
widgets/loginstatewidget.h
widgets/qsearchfield.h
osd/osdbase.h
osd/osdpretty.h
musicbrainz/acoustidclient.h
musicbrainz/musicbrainzclient.h
@ -470,10 +472,11 @@ set(UI
dialogs/userpassdialog.ui
widgets/trackslider.ui
widgets/osdpretty.ui
widgets/fileview.ui
widgets/loginstatewidget.ui
osd/osdpretty.ui
internet/internettabsview.ui
internet/internetcollectionviewcontainer.ui
internet/internetsearchview.ui
@ -524,10 +527,12 @@ optional_source(HAVE_ALSA
engine/alsadevicefinder.cpp
)
# X11
optional_source(X11_FOUND
# DBUS
optional_source(HAVE_DBUS
SOURCES
widgets/osd_x11.cpp
osd/osddbus.cpp
HEADERS
osd/osddbus.h
)
# GStreamer
@ -829,7 +834,7 @@ optional_source(APPLE
core/macsystemtrayicon.mm
core/macscreensaver.cpp
core/macfslistener.mm
widgets/osd_mac.mm
osd/osdmac.mm
widgets/qsearchfield_mac.mm
engine/macosdevicefinder.cpp
globalshortcuts/globalshortcutbackend-macos.mm
@ -837,6 +842,7 @@ optional_source(APPLE
HEADERS
core/macsystemtrayicon.h
core/macfslistener.h
osd/osdmac.h
globalshortcuts/globalshortcutbackend-macos.h
)
@ -854,7 +860,6 @@ optional_source(WIN32
SOURCES
engine/directsounddevicefinder.cpp
engine/mmdevicefinder.cpp
widgets/osd_win.cpp
core/windows7thumbbar.cpp
HEADERS
core/windows7thumbbar.h

View File

@ -106,8 +106,8 @@
#include "widgets/volumeslider.h"
#include "widgets/fileview.h"
#include "widgets/multiloadingindicator.h"
#include "widgets/osd.h"
#include "widgets/trackslider.h"
#include "osd/osdbase.h"
#include "context/contextview.h"
#include "context/contextalbumsview.h"
#include "collection/collection.h"
@ -200,7 +200,7 @@ const int kTrackSliderUpdateTimeMs = 200;
const int kTrackPositionUpdateTimeMs = 1000;
}
MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, const CommandlineOptions &options, QWidget *parent) :
MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd, const CommandlineOptions &options, QWidget *parent) :
QMainWindow(parent),
ui_(new Ui_MainWindow),
#ifdef Q_OS_WIN
@ -990,6 +990,8 @@ void MainWindow::ReloadSettings() {
}
}
osd_->ReloadSettings();
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings_.value("search_for_cover_auto", true).toBool());
#ifdef HAVE_SUBSONIC
@ -1024,7 +1026,6 @@ void MainWindow::ReloadAllSettings() {
app_->ReloadSettings();
app_->collection()->ReloadSettings();
app_->player()->ReloadSettings();
osd_->ReloadSettings();
collection_view_->ReloadSettings();
ui_->playlist->view()->ReloadSettings();
app_->playlist_manager()->playlist_container()->ReloadSettings();
@ -2516,7 +2517,7 @@ void MainWindow::ShowCoverManager() {
SettingsDialog *MainWindow::CreateSettingsDialog() {
SettingsDialog *settings_dialog = new SettingsDialog(app_, this);
SettingsDialog *settings_dialog = new SettingsDialog(app_, osd_, this);
#ifdef HAVE_GLOBALSHORTCUTS
settings_dialog->SetGlobalShortcutManager(global_shortcuts_);
#endif
@ -2695,7 +2696,7 @@ void MainWindow::AutoCompleteTagsAccepted() {
}
void MainWindow::HandleNotificationPreview(OSD::Behaviour type, QString line1, QString line2) {
void MainWindow::HandleNotificationPreview(OSDBase::Behaviour type, QString line1, QString line2) {
if (!app_->playlist_manager()->current()->GetAllSongs().isEmpty()) {
// Show a preview notification for the first song in the current playlist

View File

@ -54,7 +54,7 @@
#include "engine/enginetype.h"
#include "engine/engine_fwd.h"
#include "mac_startup.h"
#include "widgets/osd.h"
#include "osd/osdbase.h"
#include "collection/collectionmodel.h"
#include "playlist/playlistitem.h"
#include "settings/settingsdialog.h"
@ -100,7 +100,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
Q_OBJECT
public:
explicit MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, const CommandlineOptions& options, QWidget *parent = nullptr);
explicit MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd, const CommandlineOptions& options, QWidget *parent = nullptr);
~MainWindow() override;
static const char *kSettingsGroup;
@ -243,7 +243,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void Exit();
void DoExit();
void HandleNotificationPreview(const OSD::Behaviour type, QString line1, QString line2);
void HandleNotificationPreview(const OSDBase::Behaviour type, QString line1, QString line2);
void ShowConsole();
@ -288,7 +288,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
Application *app_;
SystemTrayIcon *tray_icon_;
OSD *osd_;
OSDBase *osd_;
Lazy<About> about_dialog_;
Lazy<EditTagDialog> edit_tag_dialog_;
AlbumCoverChoiceController *album_cover_choice_controller_;

View File

@ -102,7 +102,13 @@
#endif
#include "settings/behavioursettingspage.h"
#include "widgets/osd.h"
#ifdef HAVE_DBUS
# include "osd/osddbus.h"
#elif defined(Q_OS_MACOS)
# include "osd/osdmac.h"
#else
# include "osd/osdbase.h"
#endif
#ifdef HAVE_DBUS
QDBusArgument &operator<<(QDBusArgument &arg, const QImage &image);
@ -264,7 +270,13 @@ int main(int argc, char* argv[]) {
// Create the tray icon and OSD
std::unique_ptr<SystemTrayIcon> tray_icon(SystemTrayIcon::CreateSystemTrayIcon());
OSD osd(tray_icon.get(), &app);
#ifdef HAVE_DBUS
OSDDBus osd(tray_icon.get(), &app);
#elif defined(Q_OS_MACOS)
OSDMac osd(tray_icon.get(), &app);
#else
OSDBase osd(tray_icon.get(), &app);
#endif
#ifdef HAVE_DBUS
mpris::Mpris mpris(&app);

View File

@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,22 +21,14 @@
#include "config.h"
#ifdef HAVE_DBUS
# include <dbus/notification.h>
#endif
#include <QObject>
#include <QCoreApplication>
#include <QVariant>
#include <QString>
#include <QStringList>
#include <QImage>
#include <QSettings>
#ifdef HAVE_DBUS
# include <QDBusPendingCall>
#endif
#include "osd.h"
#include "osdbase.h"
#include "osdpretty.h"
#include "core/application.h"
@ -44,12 +37,13 @@
#include "core/utilities.h"
#include "covermanager/currentalbumcoverloader.h"
const char *OSD::kSettingsGroup = "OSD";
const char *OSDBase::kSettingsGroup = "OSD";
OSD::OSD(SystemTrayIcon *tray_icon, Application *app, QObject *parent)
OSDBase::OSDBase(SystemTrayIcon *tray_icon, Application *app, QObject *parent)
: QObject(parent),
app_(app),
tray_icon_(tray_icon),
pretty_popup_(new OSDPretty(OSDPretty::Mode_Popup)),
app_name_(QCoreApplication::applicationName()),
timeout_msec_(5000),
behaviour_(Native),
@ -63,28 +57,24 @@ OSD::OSD(SystemTrayIcon *tray_icon, Application *app, QObject *parent)
custom_text2_(QString()),
preview_mode_(false),
force_show_next_(false),
ignore_next_stopped_(false),
pretty_popup_(new OSDPretty(OSDPretty::Mode_Popup))
ignore_next_stopped_(false)
{
connect(app_->current_albumcover_loader(), SIGNAL(ThumbnailLoaded(Song, QUrl, QImage)), SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
ReloadSettings();
Init();
app_name_[0] = app_name_[0].toUpper();
}
OSD::~OSD() {
OSDBase::~OSDBase() {
delete pretty_popup_;
}
void OSD::ReloadSettings() {
void OSDBase::ReloadSettings() {
QSettings s;
s.beginGroup(kSettingsGroup);
behaviour_ = OSD::Behaviour(s.value("Behaviour", Native).toInt());
behaviour_ = OSDBase::Behaviour(s.value("Behaviour", Native).toInt());
timeout_msec_ = s.value("Timeout", 5000).toInt();
show_on_volume_change_ = s.value("ShowOnVolumeChange", false).toBool();
show_art_ = s.value("ShowArt", true).toBool();
@ -98,6 +88,7 @@ void OSD::ReloadSettings() {
if (!SupportsNativeNotifications() && behaviour_ == Native)
behaviour_ = Pretty;
if (!SupportsTrayPopups() && behaviour_ == TrayPopup)
behaviour_ = Disabled;
@ -106,17 +97,21 @@ void OSD::ReloadSettings() {
}
// Reload just Pretty OSD settings, not everything
void OSD::ReloadPrettyOSDSettings() {
void OSDBase::ReloadPrettyOSDSettings() {
pretty_popup_->set_popup_duration(timeout_msec_);
pretty_popup_->ReloadSettings();
}
void OSD::ReshowCurrentSong() {
void OSDBase::ReshowCurrentSong() {
force_show_next_ = true;
AlbumCoverLoaded(last_song_, last_image_uri_, last_image_);
}
void OSD::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
void OSDBase::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
// Don't change tray icon details if it's a preview
if (!preview_mode_ && tray_icon_)
@ -156,21 +151,27 @@ void OSD::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage
ReloadSettings();
preview_mode_ = false;
}
}
void OSD::Paused() {
void OSDBase::Paused() {
if (show_on_pause_) {
ShowMessage(app_name_, tr("Paused"));
}
}
void OSD::Resumed() {
void OSDBase::Resumed() {
if (show_on_resume_) {
AlbumCoverLoaded(last_song_, last_image_uri_, last_image_);
}
}
void OSD::Stopped() {
void OSDBase::Stopped() {
if (tray_icon_) tray_icon_->ClearNowPlaying();
if (ignore_next_stopped_) {
ignore_next_stopped_ = false;
@ -178,26 +179,31 @@ void OSD::Stopped() {
}
ShowMessage(app_name_, tr("Stopped"));
}
void OSD::StopAfterToggle(bool stop) {
void OSDBase::StopAfterToggle(bool stop) {
ShowMessage(app_name_, tr("Stop playing after track: %1").arg(stop ? tr("On") : tr("Off")));
}
void OSD::PlaylistFinished() {
void OSDBase::PlaylistFinished() {
// We get a PlaylistFinished followed by a Stopped from the player
ignore_next_stopped_ = true;
ShowMessage(app_name_, tr("Playlist finished"));
}
void OSD::VolumeChanged(int value) {
void OSDBase::VolumeChanged(int value) {
if (!show_on_volume_change_) return;
ShowMessage(app_name_, tr("Volume %1%").arg(value));
}
void OSD::ShowMessage(const QString &summary, const QString &message, const QString icon, const QImage &image) {
void OSDBase::ShowMessage(const QString &summary, const QString &message, const QString icon, const QImage &image) {
if (pretty_popup_->toggle_mode()) {
pretty_popup_->ShowMessage(summary, message, image);
@ -234,15 +240,8 @@ void OSD::ShowMessage(const QString &summary, const QString &message, const QStr
}
#if !defined(HAVE_X11)
#if defined(HAVE_DBUS)
void OSD::CallFinished(QDBusPendingCallWatcher*) {}
#else
void OSD::CallFinished() {}
#endif
#endif
void OSDBase::ShuffleModeChanged(PlaylistSequence::ShuffleMode mode) {
void OSD::ShuffleModeChanged(PlaylistSequence::ShuffleMode mode) {
if (show_on_play_mode_change_) {
QString current_mode = QString();
switch (mode) {
@ -253,9 +252,11 @@ void OSD::ShuffleModeChanged(PlaylistSequence::ShuffleMode mode) {
}
ShowMessage(app_name_, current_mode);
}
}
void OSD::RepeatModeChanged(PlaylistSequence::RepeatMode mode) {
void OSDBase::RepeatModeChanged(PlaylistSequence::RepeatMode mode) {
if (show_on_play_mode_change_) {
QString current_mode = QString();
switch (mode) {
@ -268,9 +269,10 @@ void OSD::RepeatModeChanged(PlaylistSequence::RepeatMode mode) {
}
ShowMessage(app_name_, current_mode);
}
}
QString OSD::ReplaceMessage(const QString &message, const Song &song) {
QString OSDBase::ReplaceMessage(const QString &message, const Song &song) {
QString newline = "<br/>";
@ -305,7 +307,7 @@ QString OSD::ReplaceMessage(const QString &message, const Song &song) {
return Utilities::ReplaceMessage(message, song, newline);
}
void OSD::ShowPreview(const Behaviour type, const QString &line1, const QString &line2, const Song &song) {
void OSDBase::ShowPreview(const Behaviour type, const QString &line1, const QString &line2, const Song &song) {
behaviour_ = type;
custom_text1_ = line1;
@ -318,7 +320,18 @@ void OSD::ShowPreview(const Behaviour type, const QString &line1, const QString
}
void OSD::SetPrettyOSDToggleMode(bool toggle) {
void OSDBase::SetPrettyOSDToggleMode(bool toggle) {
pretty_popup_->set_toggle_mode(toggle);
}
bool OSDBase::SupportsNativeNotifications() {
return false;
}
bool OSDBase::SupportsTrayPopups() {
return tray_icon_;
}
void OSDBase::ShowMessageNative(const QString&, const QString&, const QString&, const QImage&) {
qLog(Warning) << "Not implemented";
}

View File

@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,8 +19,8 @@
*
*/
#ifndef OSD_H
#define OSD_H
#ifndef OSDBASE_H
#define OSDBASE_H
#include "config.h"
@ -31,27 +32,20 @@
#include <QUrl>
#include <QDateTime>
#include <QImage>
#ifdef HAVE_DBUS
# include <QDBusArgument>
# include <QDBusPendingCall>
#endif
#include "core/song.h"
#include "playlist/playlistsequence.h"
class Application;
class OSDPretty;
class OrgFreedesktopNotificationsInterface;
class SystemTrayIcon;
class QDBusPendingCallWatcher;
class OSD : public QObject {
class OSDBase : public QObject {
Q_OBJECT
public:
explicit OSD(SystemTrayIcon *tray_icon, Application *app, QObject *parent = nullptr);
~OSD() override;
explicit OSDBase(SystemTrayIcon *tray_icon, Application *app, QObject *parent = nullptr);
~OSDBase() override;
static const char *kSettingsGroup;
@ -62,14 +56,13 @@ class OSD : public QObject {
Pretty,
};
// Implemented in the OS-specific files
static bool SupportsNativeNotifications();
static bool SupportsTrayPopups();
int timeout_msec() const { return timeout_msec_; }
void ReloadPrettyOSDSettings();
void SetPrettyOSDToggleMode(bool toggle);
virtual bool SupportsNativeNotifications();
virtual bool SupportsTrayPopups();
public slots:
void ReloadSettings();
@ -88,23 +81,17 @@ class OSD : public QObject {
private:
void ShowMessage(const QString &summary, const QString &message = QString(), const QString icon = QString("strawberry"), const QImage &image = QImage());
QString ReplaceMessage(const QString &message, const Song &song);
// These are implemented in the OS-specific files
void Init();
void ShowMessageNative(const QString &summary, const QString &message, const QString &icon = QString(), const QImage &image = QImage());
virtual void ShowMessageNative(const QString &summary, const QString &message, const QString &icon = QString(), const QImage &image = QImage());
private slots:
#ifdef HAVE_DBUS
void CallFinished(QDBusPendingCallWatcher *watcher);
#endif
void CallFinished();
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
private:
Application *app_;
SystemTrayIcon *tray_icon_;
OSDPretty *pretty_popup_;
QString app_name_;
int timeout_msec_;
Behaviour behaviour_;
@ -121,17 +108,10 @@ class OSD : public QObject {
bool force_show_next_;
bool ignore_next_stopped_;
OSDPretty *pretty_popup_;
Song last_song_;
QUrl last_image_uri_;
QImage last_image_;
#ifdef HAVE_DBUS
std::unique_ptr<OrgFreedesktopNotificationsInterface> interface_;
uint notification_id_;
QDateTime last_notification_time_;
#endif
};
#endif // OSD_H
#endif // OSDBASE_H

View File

@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,9 +23,7 @@
#include <memory>
#ifdef HAVE_DBUS
# include <dbus/notification.h>
#endif
#include <dbus/notification.h>
#include <QtGlobal>
#include <QObject>
@ -35,21 +34,18 @@
#include <QString>
#include <QStringList>
#include <QImage>
#ifdef HAVE_DBUS
# include <QCoreApplication>
# include <QDBusArgument>
# include <QDBusConnection>
# include <QDBusError>
# include <QDBusPendingCall>
# include <QDBusPendingReply>
#endif
#include <QCoreApplication>
#include <QDBusArgument>
#include <QDBusConnection>
#include <QDBusError>
#include <QDBusPendingCall>
#include <QDBusPendingReply>
#include <QDBusPendingCallWatcher>
#include <QJsonObject>
#include <QtDebug>
#include "core/logging.h"
#include "osd.h"
#ifdef HAVE_DBUS
#include "osddbus.h"
QDBusArgument &operator<< (QDBusArgument &arg, const QImage &image);
const QDBusArgument &operator>> (const QDBusArgument &arg, QImage &image);
@ -103,41 +99,38 @@ QDBusArgument &operator<<(QDBusArgument &arg, const QImage &image) {
}
const QDBusArgument &operator>>(const QDBusArgument &arg, QImage &image) {
Q_UNUSED(image);
// This is needed to link but shouldn't be called.
Q_ASSERT(0);
return arg;
}
#endif // HAVE_DBUS
void OSD::Init() {
OSDDBus::OSDDBus(SystemTrayIcon *tray_icon, Application *app, QObject *parent) : OSDBase(tray_icon, app, parent) {
Init();
}
OSDDBus::~OSDDBus() = default;
void OSDDBus::Init() {
#ifdef HAVE_DBUS
notification_id_ = 0;
interface_.reset(new OrgFreedesktopNotificationsInterface(OrgFreedesktopNotificationsInterface::staticInterfaceName(), "/org/freedesktop/Notifications", QDBusConnection::sessionBus()));
if (!interface_->isValid()) {
qLog(Warning) << "Error connecting to notifications service.";
}
#endif // HAVE_DBUS
}
bool OSD::SupportsNativeNotifications() {
bool OSDDBus::SupportsNativeNotifications() { return true; }
#ifdef HAVE_DBUS
return true;
#else
return false;
#endif
bool OSDDBus::SupportsTrayPopups() { return true; }
}
void OSDDBus::ShowMessageNative(const QString &summary, const QString &message, const QString &icon, const QImage &image) {
bool OSD::SupportsTrayPopups() { return true; }
void OSD::ShowMessageNative(const QString &summary, const QString &message, const QString &icon, const QImage &image) {
#ifdef HAVE_DBUS
if (!interface_) return;
QVariantMap hints;
@ -148,27 +141,19 @@ void OSD::ShowMessageNative(const QString &summary, const QString &message, cons
hints["transient"] = QVariant(true);
int id = 0;
if (last_notification_time_.secsTo(QDateTime::currentDateTime()) * 1000 < timeout_msec_) {
if (last_notification_time_.secsTo(QDateTime::currentDateTime()) * 1000 < timeout_msec()) {
// Reuse the existing popup if it's still open. The reason we don't always
// reuse the popup is because the notification daemon on KDE4 won't re-show the bubble if it's already gone to the tray. See issue #118
id = notification_id_;
}
QDBusPendingReply<uint> reply = interface_->Notify(QCoreApplication::applicationName(), id, icon, summary, message, QStringList(), hints, timeout_msec_);
QDBusPendingReply<uint> reply = interface_->Notify(QCoreApplication::applicationName(), id, icon, summary, message, QStringList(), hints, timeout_msec());
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(CallFinished(QDBusPendingCallWatcher*)));
#else // HAVE_DBUS
Q_UNUSED(summary)
Q_UNUSED(message)
Q_UNUSED(icon)
Q_UNUSED(image)
qLog(Warning) << "not implemented";
#endif // HAVE_DBUS
}
#ifdef HAVE_DBUS
void OSD::CallFinished(QDBusPendingCallWatcher *watcher) {
void OSDDBus::CallFinished(QDBusPendingCallWatcher *watcher) {
std::unique_ptr<QDBusPendingCallWatcher> w(watcher);
@ -183,7 +168,6 @@ void OSD::CallFinished(QDBusPendingCallWatcher *watcher) {
notification_id_ = id;
last_notification_time_ = QDateTime::currentDateTime();
}
}
#endif
void OSD::CallFinished() {}
}

70
src/osd/osddbus.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry 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.
*
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef OSDDBUS_H
#define OSDDBUS_H
#include "config.h"
#include <memory>
#include <QtGlobal>
#include <QObject>
#include <QString>
#include <QDateTime>
#include <QImage>
#include <QDBusPendingCall>
#include "osdbase.h"
class OrgFreedesktopNotificationsInterface;
class QDBusPendingCallWatcher;
class Application;
class SystemTrayIcon;
class OSDDBus : public OSDBase {
Q_OBJECT
public:
explicit OSDDBus(SystemTrayIcon *tray_icon, Application *app, QObject *parent = nullptr);
~OSDDBus() override;
static const char *kSettingsGroup;
bool SupportsNativeNotifications() override;
bool SupportsTrayPopups() override;
private:
void Init();
void ShowMessageNative(const QString &summary, const QString &message, const QString &icon = QString(), const QImage &image = QImage()) override;
private slots:
void CallFinished(QDBusPendingCallWatcher *watcher);
private:
std::unique_ptr<OrgFreedesktopNotificationsInterface> interface_;
uint notification_id_;
QDateTime last_notification_time_;
};
#endif // OSDDBUS_H

View File

@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,26 +19,28 @@
*
*/
#ifndef OSDMAC_H
#define OSDMAC_H
#include "config.h"
#include "osd.h"
#include "core/logging.h"
#include <QtGlobal>
#include <QObject>
#include <QString>
#include <QImage>
#include <QtDebug>
#include "osdbase.h"
void OSD::Init() {
}
class OSDMac : public OSDBase {
Q_OBJECT
bool OSD::SupportsNativeNotifications() {
return false;
}
public:
explicit OSDMac(SystemTrayIcon *tray_icon, Application *app, QObject *parent = nullptr);
~OSDMac() override;
bool OSD::SupportsTrayPopups() {
return true;
}
bool SupportsNativeNotifications() override;
bool SupportsTrayPopups() override;
void OSD::ShowMessageNative(const QString&, const QString&, const QString&, const QImage&) {
qLog(Warning) << "not implemented";
}
private:
void ShowMessageNative(const QString &summary, const QString &message, const QString &icon, const QImage &image) override;
};
#endif // OSDMAC_H

View File

@ -2,6 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,7 +21,7 @@
#include "config.h"
#include "osd.h"
#include "osdmac.h"
#include <QBuffer>
#include <QByteArray>
@ -35,7 +36,8 @@ bool NotificationCenterSupported() {
return NSClassFromString(@"NSUserNotificationCenter");
}
void SendNotificationCenterMessage(NSString* title, NSString* subtitle) {
void SendNotificationCenterMessage(NSString *title, NSString *subtitle) {
Class clazz = NSClassFromString(@"NSUserNotificationCenter");
id notification_center = [clazz defaultUserNotificationCenter];
@ -45,26 +47,30 @@ void SendNotificationCenterMessage(NSString* title, NSString* subtitle) {
[notification setSubtitle:subtitle];
[notification_center deliverNotification:notification];
}
}
void OSD::Init() {}
} // namespace
bool OSD::SupportsNativeNotifications() {
OSDMac::OSDMac(SystemTrayIcon *tray_icon, Application *app, QObject *parent) : OSDBase(tray_icon, app, parent) {}
OSDMac::~OSDMac() = default;
bool OSDMac::SupportsNativeNotifications() {
return NotificationCenterSupported();
}
bool OSD::SupportsTrayPopups() { return false; }
bool OSDMac::SupportsTrayPopups() { return false; }
void OSDMac::ShowMessageNative(const QString &summary, const QString &message, const QString &icon, const QImage &image) {
void OSD::ShowMessageNative(const QString& summary, const QString& message, const QString& icon, const QImage& image) {
Q_UNUSED(icon);
Q_UNUSED(image);
if (NotificationCenterSupported()) {
scoped_nsobject<NSString> mac_message(
[[NSString alloc] initWithUTF8String:message.toUtf8().constData()]);
scoped_nsobject<NSString> mac_summary(
[[NSString alloc] initWithUTF8String:summary.toUtf8().constData()]);
scoped_nsobject<NSString> mac_message([[NSString alloc] initWithUTF8String:message.toUtf8().constData()]);
scoped_nsobject<NSString> mac_summary([[NSString alloc] initWithUTF8String:summary.toUtf8().constData()]);
SendNotificationCenterMessage(mac_summary.get(), mac_message.get());
}
}

View File

@ -46,8 +46,8 @@
#include <QSettings>
#include "core/iconloader.h"
#include "widgets/osd.h"
#include "widgets/osdpretty.h"
#include "osd/osdbase.h"
#include "osd/osdpretty.h"
#include "settingspage.h"
#include "settingsdialog.h"
#include "notificationssettingspage.h"
@ -109,9 +109,9 @@ NotificationsSettingsPage::NotificationsSettingsPage(SettingsDialog* dialog)
connect(ui_->notifications_exp_chooser2, SIGNAL(triggered(QAction*)), SLOT(InsertVariableSecondLine(QAction*)));
connect(ui_->notifications_disable_duration, SIGNAL(toggled(bool)), ui_->notifications_duration, SLOT(setDisabled(bool)));
if (!OSD::SupportsNativeNotifications())
if (!dialog->osd()->SupportsNativeNotifications())
ui_->notifications_native->setEnabled(false);
if (!OSD::SupportsTrayPopups()) ui_->notifications_tray->setEnabled(false);
if (!dialog->osd()->SupportsTrayPopups()) ui_->notifications_tray->setEnabled(false);
connect(ui_->notifications_pretty, SIGNAL(toggled(bool)), SLOT(UpdatePopupVisible()));
@ -143,28 +143,28 @@ void NotificationsSettingsPage::Load() {
QSettings s;
s.beginGroup(OSD::kSettingsGroup);
OSD::Behaviour osd_behaviour = OSD::Behaviour(s.value("Behaviour", OSD::Native).toInt());
s.beginGroup(OSDBase::kSettingsGroup);
OSDBase::Behaviour osd_behaviour = OSDBase::Behaviour(s.value("Behaviour", OSDBase::Native).toInt());
switch (osd_behaviour) {
case OSD::Native:
if (OSD::SupportsNativeNotifications()) {
case OSDBase::Native:
if (dialog()->osd()->SupportsNativeNotifications()) {
ui_->notifications_native->setChecked(true);
break;
}
// Fallthrough
case OSD::Pretty:
case OSDBase::Pretty:
ui_->notifications_pretty->setChecked(true);
break;
case OSD::TrayPopup:
if (OSD::SupportsTrayPopups()) {
case OSDBase::TrayPopup:
if (dialog()->osd()->SupportsTrayPopups()) {
ui_->notifications_tray->setChecked(true);
break;
}
// Fallthrough
case OSD::Disabled:
case OSDBase::Disabled:
default:
ui_->notifications_none->setChecked(true);
break;
@ -207,13 +207,13 @@ void NotificationsSettingsPage::Save() {
QSettings s;
OSD::Behaviour osd_behaviour = OSD::Disabled;
if (ui_->notifications_none->isChecked()) osd_behaviour = OSD::Disabled;
else if (ui_->notifications_native->isChecked()) osd_behaviour = OSD::Native;
else if (ui_->notifications_tray->isChecked()) osd_behaviour = OSD::TrayPopup;
else if (ui_->notifications_pretty->isChecked()) osd_behaviour = OSD::Pretty;
OSDBase::Behaviour osd_behaviour = OSDBase::Disabled;
if (ui_->notifications_none->isChecked()) osd_behaviour = OSDBase::Disabled;
else if (ui_->notifications_native->isChecked()) osd_behaviour = OSDBase::Native;
else if (ui_->notifications_tray->isChecked()) osd_behaviour = OSDBase::TrayPopup;
else if (ui_->notifications_pretty->isChecked()) osd_behaviour = OSDBase::Pretty;
s.beginGroup(OSD::kSettingsGroup);
s.beginGroup(OSDBase::kSettingsGroup);
s.setValue("Behaviour", int(osd_behaviour));
s.setValue("Timeout", ui_->notifications_duration->value() * 1000);
s.setValue("ShowOnVolumeChange", ui_->notifications_volume->isChecked());
@ -324,15 +324,15 @@ void NotificationsSettingsPage::NotificationCustomTextChanged(bool enabled) {
void NotificationsSettingsPage::PrepareNotificationPreview() {
OSD::Behaviour notificationType = OSD::Disabled;
OSDBase::Behaviour notificationType = OSDBase::Disabled;
if (ui_->notifications_native->isChecked()) {
notificationType = OSD::Native;
notificationType = OSDBase::Native;
}
else if (ui_->notifications_pretty->isChecked()) {
notificationType = OSD::Pretty;
notificationType = OSDBase::Pretty;
}
else if (ui_->notifications_tray->isChecked()) {
notificationType = OSD::TrayPopup;
notificationType = OSDBase::TrayPopup;
}
// If user changes timeout or other options, that won't be reflected in the preview

View File

@ -112,10 +112,11 @@ void SettingsItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
}
SettingsDialog::SettingsDialog(Application *app, QMainWindow *mainwindow, QWidget *parent)
SettingsDialog::SettingsDialog(Application *app, OSDBase *osd, QMainWindow *mainwindow, QWidget *parent)
: QDialog(parent),
mainwindow_(mainwindow),
app_(app),
osd_(osd),
player_(app_->player()),
engine_(app_->player()->engine()),
model_(app_->collection_model()->directory_model()),
@ -278,7 +279,7 @@ void SettingsDialog::AddPage(Page id, SettingsPage *page, QTreeWidgetItem *paren
if (!parent) parent = ui_->list->invisibleRootItem();
// Connect page's signals to the settings dialog's signals
connect(page, SIGNAL(NotificationPreview(OSD::Behaviour, QString, QString)), SIGNAL(NotificationPreview(OSD::Behaviour, QString, QString)));
connect(page, SIGNAL(NotificationPreview(OSDBase::Behaviour, QString, QString)), SIGNAL(NotificationPreview(OSDBase::Behaviour, QString, QString)));
// Create the list item
QTreeWidgetItem *item = new QTreeWidgetItem;

View File

@ -34,7 +34,7 @@
#include <QSettings>
#include "engine/engine_fwd.h"
#include "widgets/osd.h"
#include "osd/osdbase.h"
class QMainWindow;
class QWidget;
@ -69,7 +69,7 @@ class SettingsDialog : public QDialog {
Q_OBJECT
public:
explicit SettingsDialog(Application *app, QMainWindow *mainwindow, QWidget *parent = nullptr);
explicit SettingsDialog(Application *app, OSDBase *osd, QMainWindow *mainwindow, QWidget *parent = nullptr);
~SettingsDialog() override;
enum Page {
@ -101,6 +101,7 @@ class SettingsDialog : public QDialog {
bool is_loading_settings() const { return loading_settings_; }
Application *app() const { return app_; }
OSDBase *osd() const { return osd_; }
Player *player() const { return player_; }
EngineBase *engine() const { return engine_; }
CollectionDirectoryModel *collection_directory_model() const { return model_; }
@ -138,7 +139,7 @@ class SettingsDialog : public QDialog {
signals:
void ReloadSettings();
void NotificationPreview(OSD::Behaviour, QString, QString);
void NotificationPreview(OSDBase::Behaviour, QString, QString);
private slots:
void CurrentItemChanged(QTreeWidgetItem *item);
@ -149,6 +150,7 @@ class SettingsDialog : public QDialog {
QMainWindow *mainwindow_;
Application *app_;
OSDBase *osd_;
Player *player_;
EngineBase *engine_;
CollectionDirectoryModel *model_;

View File

@ -30,7 +30,7 @@
#include <QVariant>
#include <QString>
#include "widgets/osd.h"
#include "osd/osdbase.h"
class QCheckBox;
class QComboBox;
@ -72,7 +72,7 @@ class SettingsPage : public QWidget {
virtual void Cancel() {}
signals:
void NotificationPreview(OSD::Behaviour, QString, QString);
void NotificationPreview(OSDBase::Behaviour, QString, QString);
private:
SettingsDialog *dialog_;