Hello community, here is the log from the commit of package knotifications for openSUSE:Factory checked in at 2018-10-01 08:07:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/knotifications (Old) and /work/SRC/openSUSE:Factory/.knotifications.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "knotifications" Mon Oct 1 08:07:58 2018 rev:58 rq:636014 version:5.50.0 Changes: -------- --- /work/SRC/openSUSE:Factory/knotifications/knotifications.changes 2018-08-24 16:54:53.233416863 +0200 +++ /work/SRC/openSUSE:Factory/.knotifications.new/knotifications.changes 2018-10-01 08:07:59.970301929 +0200 @@ -1,0 +2,10 @@ +Thu Sep 13 21:58:45 UTC 2018 - lbeltr...@kde.org + +- Update to 5.50.0 + * New feature release + * For more details please see: + * https://www.kde.org/announcements/kde-frameworks-5.50.0.php +- Changes since 5.49.0: + * Support libcanberra for audio notification + +------------------------------------------------------------------- Old: ---- knotifications-5.49.0.tar.xz New: ---- knotifications-5.50.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ knotifications.spec ++++++ --- /var/tmp/diff_new_pack.y37v2m/_old 2018-10-01 08:08:00.466301663 +0200 +++ /var/tmp/diff_new_pack.y37v2m/_new 2018-10-01 08:08:00.466301663 +0200 @@ -17,14 +17,14 @@ %define lname libKF5Notifications5 -%define _tar_path 5.49 +%define _tar_path 5.50 # Full KF5 version (e.g. 5.33.0) %{!?_kf5_version: %global _kf5_version %{version}} # Last major and minor KF5 version (e.g. 5.33) %{!?_kf5_bugfix_version: %define _kf5_bugfix_version %(echo %{_kf5_version} | awk -F. '{print $1"."$2}')} %bcond_without lang Name: knotifications -Version: 5.49.0 +Version: 5.50.0 Release: 0 Summary: KDE Desktop notifications License: LGPL-2.1-or-later ++++++ knotifications-5.49.0.tar.xz -> knotifications-5.50.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/CMakeLists.txt new/knotifications-5.50.0/CMakeLists.txt --- old/knotifications-5.49.0/CMakeLists.txt 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/CMakeLists.txt 2018-09-02 21:28:52.000000000 +0200 @@ -1,16 +1,16 @@ cmake_minimum_required(VERSION 3.0) -set(KF5_VERSION "5.49.0") # handled by release scripts -set(KF5_DEP_VERSION "5.49.0") # handled by release scripts +set(KF5_VERSION "5.50.0") # handled by release scripts +set(KF5_DEP_VERSION "5.50.0") # handled by release scripts project(KNotifications VERSION ${KF5_VERSION}) # ECM setup include(FeatureSummary) -find_package(ECM 5.49.0 NO_MODULE) +find_package(ECM 5.50.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) include(GenerateExportHeader) @@ -65,13 +65,23 @@ find_package(KF5Codecs ${KF5_DEP_VERSION} REQUIRED) find_package(KF5CoreAddons ${KF5_DEP_VERSION} REQUIRED) -find_package(Phonon4Qt5 4.6.60 REQUIRED NO_MODULE) -set_package_properties(Phonon4Qt5 PROPERTIES - DESCRIPTION "Qt-based audio library" - TYPE REQUIRED - PURPOSE "Required to build audio notification support") -if (Phonon4Qt5_FOUND) - add_definitions(-DHAVE_PHONON4QT5) +find_package(Canberra) +set_package_properties(Canberra PROPERTIES DESCRIPTION "Library for generating event sounds" + PURPOSE "Needed to build audio notification support" + URL "http://0pointer.de/lennart/projects/libcanberra" + TYPE OPTIONAL) +if (CANBERRA_FOUND) + add_definitions(-DHAVE_CANBERRA) +else() + find_package(Phonon4Qt5 4.6.60 NO_MODULE) + set_package_properties(Phonon4Qt5 PROPERTIES + DESCRIPTION "Qt-based audio library" + # This is REQUIRED since you cannot tell CMake "either one of those two optional ones are required" + TYPE REQUIRED + PURPOSE "Needed to build audio notification support when Canberra isn't available") + if (Phonon4Qt5_FOUND) + add_definitions(-DHAVE_PHONON4QT5) + endif() endif() remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/cmake/modules/FindCanberra.cmake new/knotifications-5.50.0/cmake/modules/FindCanberra.cmake --- old/knotifications-5.49.0/cmake/modules/FindCanberra.cmake 1970-01-01 01:00:00.000000000 +0100 +++ new/knotifications-5.50.0/cmake/modules/FindCanberra.cmake 2018-09-02 21:28:52.000000000 +0200 @@ -0,0 +1,50 @@ +# - Find libcanberra's libraries and headers. +# This module defines the following variables: +# +# CANBERRA_FOUND - true if libcanberra was found +# CANBERRA_LIBRARIES - libcanberra libraries to link against +# CANBERRA_INCLUDE_DIRS - include path for libcanberra +# +# Copyright (c) 2012 Raphael Kubo da Costa <rak...@freebsd.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +find_package(PkgConfig) +pkg_check_modules(PC_CANBERRA libcanberra) + +find_library(CANBERRA_LIBRARIES + NAMES canberra + HINTS ${PC_CANBERRA_LIBRARY_DIRS} ${PC_CANBERRA_LIBDIR} +) + +find_path(CANBERRA_INCLUDE_DIRS + NAMES canberra.h + HINTS ${PC_CANBERRA_INCLUDE_DIRS} ${PC_CANBERRA_INCLUDEDIR} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Canberra REQUIRED_VARS CANBERRA_LIBRARIES CANBERRA_INCLUDE_DIRS) + +mark_as_advanced(CANBERRA_LIBRARIES CANBERRA_INCLUDE_DIRS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/po/ar/knotifications5_qt.po new/knotifications-5.50.0/po/ar/knotifications5_qt.po --- old/knotifications-5.49.0/po/ar/knotifications5_qt.po 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/po/ar/knotifications5_qt.po 2018-09-02 21:28:52.000000000 +0200 @@ -1,19 +1,19 @@ -# Safa Alfulaij <safa1996alful...@gmail.com>, 2014. +# Safa Alfulaij <safa1996alful...@gmail.com>, 2014, 2018. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-06-28 15:38+0300\n" -"PO-Revision-Date: 2014-05-08 20:10+0300\n" +"PO-Revision-Date: 2018-06-09 21:05+0300\n" "Last-Translator: Safa Alfulaij <safa1996alful...@gmail.com>\n" -"Language-Team: Arabic <kde-i18n-...@kde.org>\n" +"Language-Team: Arabic <d...@arabeyes.org>\n" "Language: ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" -"X-Generator: Lokalize 1.5\n" +"X-Generator: Lokalize 2.0\n" "X-Qt-Contexts: true\n" #: knotificationrestrictions.cpp:192 @@ -40,9 +40,9 @@ #, qt-format msgctxt "KStatusNotifierItem|" msgid "<qt>Are you sure you want to quit <b>%1</b>?</qt>" -msgstr "<qt>أأنت متأكد من إنهاء <b>%1</b>؟</qt>" +msgstr "أمتأكّد من إنهاء <b>%1</b>؟" #: kstatusnotifieritem.cpp:1066 msgctxt "KStatusNotifierItem|" msgid "Confirm Quit From System Tray" -msgstr "أكِّد الإنهاء من صينية النظام" +msgstr "أكّد الإنهاء من صينية النظام" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/po/zh_CN/knotifications5_qt.po new/knotifications-5.50.0/po/zh_CN/knotifications5_qt.po --- old/knotifications-5.49.0/po/zh_CN/knotifications5_qt.po 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/po/zh_CN/knotifications5_qt.po 2018-09-02 21:28:52.000000000 +0200 @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: kdeorg\n" -"PO-Revision-Date: 2018-07-24 08:41\n" -"Last-Translator: guoyunhebrave <guoyunhebr...@gmail.com>\n" +"PO-Revision-Date: 2018-08-30 13:09\n" +"Last-Translator: guoyunhebrave <yunhe....@protonmail.com>\n" "Language-Team: Chinese Simplified\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/CMakeLists.txt new/knotifications-5.50.0/src/CMakeLists.txt --- old/knotifications-5.49.0/src/CMakeLists.txt 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/src/CMakeLists.txt 2018-09-02 21:28:52.000000000 +0200 @@ -1,6 +1,9 @@ if (Phonon4Qt5_FOUND) include_directories(${PHONON_INCLUDE_DIR}) endif() +if (CANBERRA_FOUND) + include_directories(${CANBERRA_INCLUDE_DIRS}) +endif() ecm_create_qm_loader(knotifications_QM_LOADER knotifications5_qt) @@ -27,9 +30,12 @@ ecm_qt_declare_logging_category(knotifications_SRCS HEADER debug_p.h IDENTIFIER LOG_KNOTIFICATIONS CATEGORY_NAME org.kde.knotifications) -if (Phonon4Qt5_FOUND) +if (CANBERRA_FOUND) + set(knotifications_SRCS ${knotifications_SRCS} + notifybyaudio_canberra.cpp) +elseif (Phonon4Qt5_FOUND) set(knotifications_SRCS ${knotifications_SRCS} - notifybyaudio.cpp) + notifybyaudio_phonon.cpp) endif() if (Qt5TextToSpeech_FOUND) @@ -82,6 +88,11 @@ ${PHONON_LIBRARIES}) endif() +if (CANBERRA_FOUND) + target_link_libraries(KF5Notifications PRIVATE + ${CANBERRA_LIBRARIES}) +endif() + if (Qt5TextToSpeech_FOUND) target_link_libraries(KF5Notifications PRIVATE Qt5::TextToSpeech) endif() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/knotificationmanager.cpp new/knotifications-5.50.0/src/knotificationmanager.cpp --- old/knotifications-5.49.0/src/knotificationmanager.cpp 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/src/knotificationmanager.cpp 2018-09-02 21:28:52.000000000 +0200 @@ -41,8 +41,10 @@ #include "notifybyflatpak.h" #include "debug_p.h" -#ifdef HAVE_PHONON4QT5 -#include "notifybyaudio.h" +#if defined(HAVE_CANBERRA) +#include "notifybyaudio_canberra.h" +#elif defined(HAVE_PHONON4QT5) +#include "notifybyaudio_phonon.h" #endif #ifdef HAVE_SPEECH @@ -137,7 +139,7 @@ plugin = new NotifyByTaskbar(this); addPlugin(plugin); } else if (action == QLatin1String("Sound")) { -#ifdef HAVE_PHONON4QT5 +#if defined(HAVE_PHONON4QT5) || defined(HAVE_CANBERRA) plugin = new NotifyByAudio(this); addPlugin(plugin); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/notifybyaudio.cpp new/knotifications-5.50.0/src/notifybyaudio.cpp --- old/knotifications-5.49.0/src/notifybyaudio.cpp 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/src/notifybyaudio.cpp 1970-01-01 01:00:00.000000000 +0100 @@ -1,188 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2014-2015 by Martin Klapetek <mklape...@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) version 3, or any - later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), which shall - act as a proxy defined in Section 6 of version 3 of the license. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "notifybyaudio.h" -#include "debug_p.h" - -#include <QDateTime> -#include <QFile> -#include <QTextStream> -#include <QUrl> -#include <QString> - -#include "knotifyconfig.h" -#include "knotification.h" - -#include <phonon/mediaobject.h> -#include <phonon/mediasource.h> -#include <phonon/audiooutput.h> - -NotifyByAudio::NotifyByAudio(QObject *parent) - : KNotificationPlugin(parent), - m_audioOutput(nullptr) -{ -} - -NotifyByAudio::~NotifyByAudio() -{ - qDeleteAll(m_reusablePhonons); - delete m_audioOutput; -} - -void NotifyByAudio::notify(KNotification *notification, KNotifyConfig *config) -{ - if (!m_audioOutput) { - m_audioOutput = new Phonon::AudioOutput(Phonon::NotificationCategory, this); - } - const QString soundFilename = config->readEntry(QStringLiteral("Sound")); - if (soundFilename.isEmpty()) { - qCWarning(LOG_KNOTIFICATIONS) << "Audio notification requested, but no sound file provided in notifyrc file, aborting audio notification"; - - finish(notification); - return; - } - - QUrl soundURL; - const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); - for (const QString &dataLocation : dataLocations) { - soundURL = QUrl::fromUserInput(soundFilename, - dataLocation + QStringLiteral("/sounds"), - QUrl::AssumeLocalFile); - if (soundURL.isLocalFile() && QFile::exists(soundURL.toLocalFile())) { - break; - } else if (!soundURL.isLocalFile() && soundURL.isValid()) { - break; - } - soundURL.clear(); - } - if (soundURL.isEmpty()) { - qCWarning(LOG_KNOTIFICATIONS) << "Audio notification requested, but sound file from notifyrc file was not found, aborting audio notification"; - finish(notification); - return; - } - - Phonon::MediaObject *m; - - if (m_reusablePhonons.isEmpty()) { - m = new Phonon::MediaObject(this); - connect(m, &Phonon::MediaObject::finished, this, &NotifyByAudio::onAudioFinished); - connect(m, &Phonon::MediaObject::stateChanged, this, &NotifyByAudio::stateChanged); - Phonon::createPath(m, m_audioOutput); - } else { - m = m_reusablePhonons.takeFirst(); - } - - m->setCurrentSource(soundURL); - m->play(); - - if (notification->flags() & KNotification::LoopSound) { - // Enqueing essentially prevents the subsystem pipeline from partial teardown - // which is the most desired thing in terms of load and delay between loop cycles. - // All of this is timing dependent, which is why we want at least one source queued; - // in reality the shorter the source the more sources we want to be queued to prevent - // the MO from running out of sources. - // Point being that all phonon signals are forcefully queued (becuase qthread has problems detecting !pthread threads), - // so when you get for example the aboutToFinish signal the MO might already have stopped playing. - // - // And so we queue it three times at least; doesn't cost anything and keeps us safe. - - m->enqueue(soundURL); - m->enqueue(soundURL); - m->enqueue(soundURL); - - connect(m, SIGNAL(currentSourceChanged(Phonon::MediaSource)), SLOT(onAudioSourceChanged(Phonon::MediaSource))); - } - - Q_ASSERT(!m_notifications.value(m)); - m_notifications.insert(m, notification); -} - -void NotifyByAudio::stateChanged(Phonon::State newState, Phonon::State oldState) -{ - qCDebug(LOG_KNOTIFICATIONS) << "Changing audio state from" << oldState << "to" << newState; -} - -void NotifyByAudio::close(KNotification *notification) -{ - Phonon::MediaObject *m = m_notifications.key(notification); - - if (!m) { - return; - } - - m->stop(); - finishNotification(notification, m); -} - -void NotifyByAudio::onAudioFinished() -{ - Phonon::MediaObject *m = qobject_cast<Phonon::MediaObject*>(sender()); - - if (!m) { - return; - } - - KNotification *notification = m_notifications.value(m, nullptr); - - if (!notification) { - // This means that close was called already so there's nothing else to do. - // Ideally we should not be getting here if close has already been called - // since stoping a mediaobject means it won't emit finished() *BUT* - // since the finished signal is a queued connection in phonon it can happen - // that the playing had already finished and we just had not got the signal yet - return; - } - - //if the sound is short enough, we can't guarantee new sounds are - //enqueued before finished is emitted. - //so to make sure we are looping restart it when the sound finished - if (notification && (notification->flags() & KNotification::LoopSound)) { - m->play(); - return; - } - - finishNotification(notification, m); -} - -void NotifyByAudio::finishNotification(KNotification *notification, Phonon::MediaObject *m) -{ - m_notifications.remove(m); - - if (notification) { - finish(notification); - } - - disconnect(m, SIGNAL(currentSourceChanged(Phonon::MediaSource)), this, SLOT(onAudioSourceChanged(Phonon::MediaSource))); - - m_reusablePhonons.append(m); -} - -void NotifyByAudio::onAudioSourceChanged(const Phonon::MediaSource &source) -{ - Phonon::MediaObject *m = qobject_cast<Phonon::MediaObject*>(sender()); - - if (!m) { - return; - } - - m->enqueue(source); -} - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/notifybyaudio.h new/knotifications-5.50.0/src/notifybyaudio.h --- old/knotifications-5.49.0/src/notifybyaudio.h 2018-08-04 13:00:11.000000000 +0200 +++ new/knotifications-5.50.0/src/notifybyaudio.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,64 +0,0 @@ -/* This file is part of the KDE libraries - Copyright 2014 by Martin Klapetek <mklape...@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) version 3, or any - later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), which shall - act as a proxy defined in Section 6 of version 3 of the license. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library. If not, see <http://www.gnu.org/licenses/>. - -*/ - - -#ifndef NOTIFYBYAUDIO_H -#define NOTIFYBYAUDIO_H - -#include "knotificationplugin.h" - -#include <phonon/MediaObject> - -namespace Phonon { -// class MediaObject; -class MediaSource; -class AudioOutput; -} - -class KNotification; - -class NotifyByAudio : public KNotificationPlugin -{ - Q_OBJECT - -public: - explicit NotifyByAudio(QObject *parent = nullptr); - ~NotifyByAudio() override; - - QString optionName() override { return QStringLiteral("Sound"); } - void notify(KNotification *notification, KNotifyConfig *config) override; - void close(KNotification *notification) override; - -private Q_SLOTS: - void onAudioFinished(); - void onAudioSourceChanged(const Phonon::MediaSource &source); - void stateChanged(Phonon::State newState, Phonon::State oldState); - - -private: - void finishNotification(KNotification *notification, Phonon::MediaObject *m); - - QList<Phonon::MediaObject*> m_reusablePhonons; - QHash<Phonon::MediaObject*, KNotification*> m_notifications; - Phonon::AudioOutput *m_audioOutput; -}; - -#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/notifybyaudio_canberra.cpp new/knotifications-5.50.0/src/notifybyaudio_canberra.cpp --- old/knotifications-5.49.0/src/notifybyaudio_canberra.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/knotifications-5.50.0/src/notifybyaudio_canberra.cpp 2018-09-02 21:28:52.000000000 +0200 @@ -0,0 +1,190 @@ +/* This file is part of the KDE libraries + Copyright (C) 2014-2015 by Martin Klapetek <mklape...@kde.org> + Copyright (C) 2018 Kai Uwe Broulik <k...@privat.broulik.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "notifybyaudio_canberra.h" +#include "debug_p.h" + +#include <QGuiApplication> +#include <QFile> +#include <QFileInfo> +#include <QIcon> +#include <QString> + +#include "knotifyconfig.h" +#include "knotification.h" + +#include <canberra.h> + +NotifyByAudio::NotifyByAudio(QObject *parent) + : KNotificationPlugin(parent) +{ + qRegisterMetaType<uint32_t>("uint32_t"); + + int ret = ca_context_create(&m_context); + if (ret != CA_SUCCESS) { + qCWarning(LOG_KNOTIFICATIONS) << "Failed to initialize canberra context for audio notification:" << ca_strerror(ret); + m_context = nullptr; + return; + } + + ret = ca_context_change_props(m_context, + CA_PROP_APPLICATION_NAME, qUtf8Printable(qApp->applicationDisplayName()), + CA_PROP_APPLICATION_ID, qUtf8Printable(qApp->desktopFileName()), + CA_PROP_APPLICATION_ICON_NAME, qUtf8Printable(qApp->windowIcon().name()), + nullptr); + if (ret != CA_SUCCESS) { + qCWarning(LOG_KNOTIFICATIONS) << "Failed to set application properties on canberra context for audio notification:" << ca_strerror(ret); + } +} + +NotifyByAudio::~NotifyByAudio() +{ + if (m_context) { + ca_context_destroy(m_context); + } + m_context = nullptr; +} + +void NotifyByAudio::notify(KNotification *notification, KNotifyConfig *config) +{ + const QString soundFilename = config->readEntry(QStringLiteral("Sound")); + if (soundFilename.isEmpty()) { + qCWarning(LOG_KNOTIFICATIONS) << "Audio notification requested, but no sound file provided in notifyrc file, aborting audio notification"; + + finish(notification); + return; + } + + QUrl soundURL; + const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + for (const QString &dataLocation : dataLocations) { + soundURL = QUrl::fromUserInput(soundFilename, + dataLocation + QStringLiteral("/sounds"), + QUrl::AssumeLocalFile); + if (soundURL.isLocalFile() && QFileInfo::exists(soundURL.toLocalFile())) { + break; + } else if (!soundURL.isLocalFile() && soundURL.isValid()) { + break; + } + soundURL.clear(); + } + if (soundURL.isEmpty()) { + qCWarning(LOG_KNOTIFICATIONS) << "Audio notification requested, but sound file from notifyrc file was not found, aborting audio notification"; + finish(notification); + return; + } + + // Looping happens in the finishCallback + if (!playSound(m_currentId, soundURL)) { + finish(notification); + return; + } + + if (notification->flags() & KNotification::LoopSound) { + m_loopSoundUrls.insert(m_currentId, soundURL); + } + + Q_ASSERT(!m_notifications.value(m_currentId)); + m_notifications.insert(m_currentId, notification); + + ++m_currentId; +} + +bool NotifyByAudio::playSound(quint32 id, const QUrl &url) +{ + if (!m_context) { + qCWarning(LOG_KNOTIFICATIONS) << "Cannot play notification sound without canberra context"; + return false; + } + + ca_proplist *props = nullptr; + ca_proplist_create(&props); + + // We'll also want this cached for a time. volatile makes sure the cache is + // dropped after some time or when the cache is under pressure. + ca_proplist_sets(props, CA_PROP_MEDIA_FILENAME, QFile::encodeName(url.toLocalFile()).constData()); + ca_proplist_sets(props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile"); + + int ret = ca_context_play_full(m_context, id, props, &ca_finish_callback, this); + + ca_proplist_destroy(props); + + if (ret != CA_SUCCESS) { + qCWarning(LOG_KNOTIFICATIONS) << "Failed to play sound with canberra:" << ca_strerror(ret); + return false; + } + + return true; +} + +void NotifyByAudio::ca_finish_callback(ca_context *c, uint32_t id, int error_code, void *userdata) +{ + Q_UNUSED(c); + QMetaObject::invokeMethod(static_cast<NotifyByAudio*>(userdata), + "finishCallback", + Q_ARG(uint32_t, id), + Q_ARG(int, error_code)); +} + +void NotifyByAudio::finishCallback(uint32_t id, int error_code) +{ + KNotification *notification = m_notifications.value(id, nullptr); + + if (error_code == CA_SUCCESS) { + // Loop the sound now if we have one + const QUrl soundUrl = m_loopSoundUrls.value(id); + if (soundUrl.isValid()) { + if (!playSound(id, soundUrl)) { + finishNotification(notification, id); + } + return; + } + } else if (error_code != CA_ERROR_CANCELED) { + qCWarning(LOG_KNOTIFICATIONS) << "Playing audio notification failed:" << ca_strerror(error_code); + } + + finishNotification(notification, id); +} + +void NotifyByAudio::close(KNotification *notification) +{ + if (!m_notifications.values().contains(notification)) { + return; + } + + const auto id = m_notifications.key(notification); + if (m_context) { + int ret = ca_context_cancel(m_context, id); + if (ret != CA_SUCCESS) { + qCWarning(LOG_KNOTIFICATIONS) << "Failed to cancel canberra context for audio notification:" << ca_strerror(ret); + return; + } + } +} + + +void NotifyByAudio::finishNotification(KNotification *notification, quint32 id) +{ + m_notifications.remove(id); + m_loopSoundUrls.remove(id); + finish(notification); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/notifybyaudio_canberra.h new/knotifications-5.50.0/src/notifybyaudio_canberra.h --- old/knotifications-5.49.0/src/notifybyaudio_canberra.h 1970-01-01 01:00:00.000000000 +0100 +++ new/knotifications-5.50.0/src/notifybyaudio_canberra.h 2018-09-02 21:28:52.000000000 +0200 @@ -0,0 +1,68 @@ +/* This file is part of the KDE libraries + Copyright 2014 by Martin Klapetek <mklape...@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#ifndef NOTIFYBYAUDIO_H +#define NOTIFYBYAUDIO_H + +#include "knotificationplugin.h" + +#include <QHash> +#include <QUrl> + +class KNotification; + +struct ca_context; + +class NotifyByAudio : public KNotificationPlugin +{ + Q_OBJECT + +public: + explicit NotifyByAudio(QObject *parent = nullptr); + ~NotifyByAudio() override; + + QString optionName() override { return QStringLiteral("Sound"); } + void notify(KNotification *notification, KNotifyConfig *config) override; + void close(KNotification *notification) override; + +private Q_SLOTS: + void finishCallback(uint32_t id, + int error_code); + +private: + static void ca_finish_callback(ca_context *c, + uint32_t id, + int error_code, + void *userdata); + + void finishNotification(KNotification *notification, quint32 id); + + bool playSound(quint32 id, const QUrl &url); + + ca_context *m_context = nullptr; + quint32 m_currentId = 0; + QHash<quint32, KNotification*> m_notifications; + // in case we loop we store the URL for the notification to be able to replay it + QHash<quint32, QUrl> m_loopSoundUrls; +}; + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/notifybyaudio_phonon.cpp new/knotifications-5.50.0/src/notifybyaudio_phonon.cpp --- old/knotifications-5.49.0/src/notifybyaudio_phonon.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/knotifications-5.50.0/src/notifybyaudio_phonon.cpp 2018-09-02 21:28:52.000000000 +0200 @@ -0,0 +1,188 @@ +/* This file is part of the KDE libraries + Copyright (C) 2014-2015 by Martin Klapetek <mklape...@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "notifybyaudio_phonon.h" +#include "debug_p.h" + +#include <QDateTime> +#include <QFile> +#include <QTextStream> +#include <QUrl> +#include <QString> + +#include "knotifyconfig.h" +#include "knotification.h" + +#include <phonon/mediaobject.h> +#include <phonon/mediasource.h> +#include <phonon/audiooutput.h> + +NotifyByAudio::NotifyByAudio(QObject *parent) + : KNotificationPlugin(parent), + m_audioOutput(nullptr) +{ +} + +NotifyByAudio::~NotifyByAudio() +{ + qDeleteAll(m_reusablePhonons); + delete m_audioOutput; +} + +void NotifyByAudio::notify(KNotification *notification, KNotifyConfig *config) +{ + if (!m_audioOutput) { + m_audioOutput = new Phonon::AudioOutput(Phonon::NotificationCategory, this); + } + const QString soundFilename = config->readEntry(QStringLiteral("Sound")); + if (soundFilename.isEmpty()) { + qCWarning(LOG_KNOTIFICATIONS) << "Audio notification requested, but no sound file provided in notifyrc file, aborting audio notification"; + + finish(notification); + return; + } + + QUrl soundURL; + const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + for (const QString &dataLocation : dataLocations) { + soundURL = QUrl::fromUserInput(soundFilename, + dataLocation + QStringLiteral("/sounds"), + QUrl::AssumeLocalFile); + if (soundURL.isLocalFile() && QFile::exists(soundURL.toLocalFile())) { + break; + } else if (!soundURL.isLocalFile() && soundURL.isValid()) { + break; + } + soundURL.clear(); + } + if (soundURL.isEmpty()) { + qCWarning(LOG_KNOTIFICATIONS) << "Audio notification requested, but sound file from notifyrc file was not found, aborting audio notification"; + finish(notification); + return; + } + + Phonon::MediaObject *m; + + if (m_reusablePhonons.isEmpty()) { + m = new Phonon::MediaObject(this); + connect(m, &Phonon::MediaObject::finished, this, &NotifyByAudio::onAudioFinished); + connect(m, &Phonon::MediaObject::stateChanged, this, &NotifyByAudio::stateChanged); + Phonon::createPath(m, m_audioOutput); + } else { + m = m_reusablePhonons.takeFirst(); + } + + m->setCurrentSource(soundURL); + m->play(); + + if (notification->flags() & KNotification::LoopSound) { + // Enqueing essentially prevents the subsystem pipeline from partial teardown + // which is the most desired thing in terms of load and delay between loop cycles. + // All of this is timing dependent, which is why we want at least one source queued; + // in reality the shorter the source the more sources we want to be queued to prevent + // the MO from running out of sources. + // Point being that all phonon signals are forcefully queued (becuase qthread has problems detecting !pthread threads), + // so when you get for example the aboutToFinish signal the MO might already have stopped playing. + // + // And so we queue it three times at least; doesn't cost anything and keeps us safe. + + m->enqueue(soundURL); + m->enqueue(soundURL); + m->enqueue(soundURL); + + connect(m, SIGNAL(currentSourceChanged(Phonon::MediaSource)), SLOT(onAudioSourceChanged(Phonon::MediaSource))); + } + + Q_ASSERT(!m_notifications.value(m)); + m_notifications.insert(m, notification); +} + +void NotifyByAudio::stateChanged(Phonon::State newState, Phonon::State oldState) +{ + qCDebug(LOG_KNOTIFICATIONS) << "Changing audio state from" << oldState << "to" << newState; +} + +void NotifyByAudio::close(KNotification *notification) +{ + Phonon::MediaObject *m = m_notifications.key(notification); + + if (!m) { + return; + } + + m->stop(); + finishNotification(notification, m); +} + +void NotifyByAudio::onAudioFinished() +{ + Phonon::MediaObject *m = qobject_cast<Phonon::MediaObject*>(sender()); + + if (!m) { + return; + } + + KNotification *notification = m_notifications.value(m, nullptr); + + if (!notification) { + // This means that close was called already so there's nothing else to do. + // Ideally we should not be getting here if close has already been called + // since stoping a mediaobject means it won't emit finished() *BUT* + // since the finished signal is a queued connection in phonon it can happen + // that the playing had already finished and we just had not got the signal yet + return; + } + + //if the sound is short enough, we can't guarantee new sounds are + //enqueued before finished is emitted. + //so to make sure we are looping restart it when the sound finished + if (notification && (notification->flags() & KNotification::LoopSound)) { + m->play(); + return; + } + + finishNotification(notification, m); +} + +void NotifyByAudio::finishNotification(KNotification *notification, Phonon::MediaObject *m) +{ + m_notifications.remove(m); + + if (notification) { + finish(notification); + } + + disconnect(m, SIGNAL(currentSourceChanged(Phonon::MediaSource)), this, SLOT(onAudioSourceChanged(Phonon::MediaSource))); + + m_reusablePhonons.append(m); +} + +void NotifyByAudio::onAudioSourceChanged(const Phonon::MediaSource &source) +{ + Phonon::MediaObject *m = qobject_cast<Phonon::MediaObject*>(sender()); + + if (!m) { + return; + } + + m->enqueue(source); +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knotifications-5.49.0/src/notifybyaudio_phonon.h new/knotifications-5.50.0/src/notifybyaudio_phonon.h --- old/knotifications-5.49.0/src/notifybyaudio_phonon.h 1970-01-01 01:00:00.000000000 +0100 +++ new/knotifications-5.50.0/src/notifybyaudio_phonon.h 2018-09-02 21:28:52.000000000 +0200 @@ -0,0 +1,64 @@ +/* This file is part of the KDE libraries + Copyright 2014 by Martin Klapetek <mklape...@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#ifndef NOTIFYBYAUDIO_H +#define NOTIFYBYAUDIO_H + +#include "knotificationplugin.h" + +#include <phonon/MediaObject> + +namespace Phonon { +// class MediaObject; +class MediaSource; +class AudioOutput; +} + +class KNotification; + +class NotifyByAudio : public KNotificationPlugin +{ + Q_OBJECT + +public: + explicit NotifyByAudio(QObject *parent = nullptr); + ~NotifyByAudio() override; + + QString optionName() override { return QStringLiteral("Sound"); } + void notify(KNotification *notification, KNotifyConfig *config) override; + void close(KNotification *notification) override; + +private Q_SLOTS: + void onAudioFinished(); + void onAudioSourceChanged(const Phonon::MediaSource &source); + void stateChanged(Phonon::State newState, Phonon::State oldState); + + +private: + void finishNotification(KNotification *notification, Phonon::MediaObject *m); + + QList<Phonon::MediaObject*> m_reusablePhonons; + QHash<Phonon::MediaObject*, KNotification*> m_notifications; + Phonon::AudioOutput *m_audioOutput; +}; + +#endif