diff --git a/debian/copyright b/debian/copyright index 73f6e989..f4f651b5 100644 --- a/debian/copyright +++ b/debian/copyright @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21a69651..94a5e620 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index f7a4ecef..763b5c9f 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -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 diff --git a/src/core/mainwindow.h b/src/core/mainwindow.h index 140ccaa7..3552ae7b 100644 --- a/src/core/mainwindow.h +++ b/src/core/mainwindow.h @@ -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_dialog_; Lazy edit_tag_dialog_; AlbumCoverChoiceController *album_cover_choice_controller_; diff --git a/src/main.cpp b/src/main.cpp index 59a31ff0..71c0f007 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 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); diff --git a/src/widgets/osd.cpp b/src/osd/osdbase.cpp similarity index 83% rename from src/widgets/osd.cpp rename to src/osd/osdbase.cpp index b0b53045..711a85f2 100644 --- a/src/widgets/osd.cpp +++ b/src/osd/osdbase.cpp @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2018-2020, Jonas Kvinge * * 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 -#endif - #include #include -#include #include #include #include #include -#ifdef HAVE_DBUS -# include -#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 = "
"; @@ -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"; +} diff --git a/src/widgets/osd.h b/src/osd/osdbase.h similarity index 73% rename from src/widgets/osd.h rename to src/osd/osdbase.h index 698c8ef0..855f2e22 100644 --- a/src/widgets/osd.h +++ b/src/osd/osdbase.h @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2018-2020, Jonas Kvinge * * 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 #include #include -#ifdef HAVE_DBUS -# include -# include -#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 interface_; - uint notification_id_; - QDateTime last_notification_time_; -#endif }; -#endif // OSD_H +#endif // OSDBASE_H diff --git a/src/widgets/osd_x11.cpp b/src/osd/osddbus.cpp similarity index 81% rename from src/widgets/osd_x11.cpp rename to src/osd/osddbus.cpp index 2b4a1739..1904a463 100644 --- a/src/widgets/osd_x11.cpp +++ b/src/osd/osddbus.cpp @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2018-2020, Jonas Kvinge * * 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 -#ifdef HAVE_DBUS -# include -#endif +#include #include #include @@ -35,21 +34,18 @@ #include #include #include -#ifdef HAVE_DBUS -# include -# include -# include -# include -# include -# include -#endif +#include +#include +#include +#include +#include +#include +#include #include #include #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 reply = interface_->Notify(QCoreApplication::applicationName(), id, icon, summary, message, QStringList(), hints, timeout_msec_); + QDBusPendingReply 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 w(watcher); @@ -183,7 +168,6 @@ void OSD::CallFinished(QDBusPendingCallWatcher *watcher) { notification_id_ = id; last_notification_time_ = QDateTime::currentDateTime(); } -} -#endif -void OSD::CallFinished() {} + +} diff --git a/src/osd/osddbus.h b/src/osd/osddbus.h new file mode 100644 index 00000000..cb38df64 --- /dev/null +++ b/src/osd/osddbus.h @@ -0,0 +1,70 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * Copyright 2018-2020, Jonas Kvinge + * + * 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 . + * + */ + +#ifndef OSDDBUS_H +#define OSDDBUS_H + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include + +#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 interface_; + uint notification_id_; + QDateTime last_notification_time_; + +}; + +#endif // OSDDBUS_H diff --git a/src/widgets/osd_win.cpp b/src/osd/osdmac.h similarity index 58% rename from src/widgets/osd_win.cpp rename to src/osd/osdmac.h index a49b4c21..2b18d7b5 100644 --- a/src/widgets/osd_win.cpp +++ b/src/osd/osdmac.h @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2018-2020, Jonas Kvinge * * 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 +#include -#include -#include -#include +#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 diff --git a/src/widgets/osd_mac.mm b/src/osd/osdmac.mm similarity index 68% rename from src/widgets/osd_mac.mm rename to src/osd/osdmac.mm index 8a3b3144..60d931c4 100644 --- a/src/widgets/osd_mac.mm +++ b/src/osd/osdmac.mm @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2018-2020, Jonas Kvinge * * 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 #include @@ -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 mac_message( - [[NSString alloc] initWithUTF8String:message.toUtf8().constData()]); - scoped_nsobject mac_summary( - [[NSString alloc] initWithUTF8String:summary.toUtf8().constData()]); + scoped_nsobject mac_message([[NSString alloc] initWithUTF8String:message.toUtf8().constData()]); + scoped_nsobject mac_summary([[NSString alloc] initWithUTF8String:summary.toUtf8().constData()]); SendNotificationCenterMessage(mac_summary.get(), mac_message.get()); } + } diff --git a/src/widgets/osdpretty.cpp b/src/osd/osdpretty.cpp similarity index 100% rename from src/widgets/osdpretty.cpp rename to src/osd/osdpretty.cpp diff --git a/src/widgets/osdpretty.h b/src/osd/osdpretty.h similarity index 100% rename from src/widgets/osdpretty.h rename to src/osd/osdpretty.h diff --git a/src/widgets/osdpretty.ui b/src/osd/osdpretty.ui similarity index 100% rename from src/widgets/osdpretty.ui rename to src/osd/osdpretty.ui diff --git a/src/settings/notificationssettingspage.cpp b/src/settings/notificationssettingspage.cpp index 77041a85..6140c908 100644 --- a/src/settings/notificationssettingspage.cpp +++ b/src/settings/notificationssettingspage.cpp @@ -46,8 +46,8 @@ #include #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 diff --git a/src/settings/settingsdialog.cpp b/src/settings/settingsdialog.cpp index 02fbdc31..935c051e 100644 --- a/src/settings/settingsdialog.cpp +++ b/src/settings/settingsdialog.cpp @@ -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; diff --git a/src/settings/settingsdialog.h b/src/settings/settingsdialog.h index 438fe093..8b937d02 100644 --- a/src/settings/settingsdialog.h +++ b/src/settings/settingsdialog.h @@ -34,7 +34,7 @@ #include #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_; diff --git a/src/settings/settingspage.h b/src/settings/settingspage.h index a9e95966..ed7e8d21 100644 --- a/src/settings/settingspage.h +++ b/src/settings/settingspage.h @@ -30,7 +30,7 @@ #include #include -#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_;