swift
notificationplayer.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2016 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "notificationplayer.h"
5 
6 #include <QTimer>
7 
8 #include "misc/logmessage.h"
11 
12 using namespace swift::misc;
13 using namespace swift::misc::audio;
14 using namespace swift::sound::sample_provider;
15 
16 namespace swift::sound
17 {
18  CNotificationPlayer::CNotificationPlayer(QObject *parent) : QObject(parent)
19  {
20  // lazy init at play
21  }
22 
24  {
25  QSoundEffect *effect = m_effects.value(notification, nullptr);
26  if (effect)
27  {
28  if (!m_playingEffect && effect->isLoaded() && !effect->isPlaying())
29  {
30  const int currentEffect = ++m_playingEffectCounter;
31  const qreal v = volume / 100.0f;
32  m_playingEffect = effect;
33  effect->setVolume(v); // 0..1
34  effect->play();
35 
36  // used for too long or hanging sounds
37  QPointer<CNotificationPlayer> myself(this);
38  QTimer::singleShot(3000, effect, [=] {
39  if (!myself || !m_playingEffect) { return; }
40  if (currentEffect != m_playingEffectCounter) { return; }
41  m_playingEffect->stop();
42  });
43  }
44  }
45  }
46 
47  void CNotificationPlayer::updateDirectory(const QString &directory)
48  {
49  if (directory == m_directory && !m_effects.isEmpty()) { return; }
50  m_directory = directory;
51 
52  const QStringList types = QSoundEffect::supportedMimeTypes();
53  CLogMessage(this).info(u"Notification mime types: %1") << types.join(", ");
54 
55  this->updateEffect(CNotificationSounds::NotificationLogin, directory, "login.wav");
56  this->updateEffect(CNotificationSounds::NotificationLogoff, directory, "logoff.wav");
57  this->updateEffect(CNotificationSounds::NotificationTextMessageFrequency, directory, "frequencymessage.wav");
58  this->updateEffect(CNotificationSounds::NotificationTextMessagePrivate, directory, "privatemessage.wav");
59  this->updateEffect(CNotificationSounds::NotificationTextMessageSupervisor, directory, "supervisormessage.wav");
60  this->updateEffect(CNotificationSounds::NotificationTextMessageUnicom, directory, "unicommessage.wav");
61  this->updateEffect(CNotificationSounds::NotificationTextCallsignMentioned, directory, "callsignmentioned.wav");
62  this->updateEffect(CNotificationSounds::PTTClickKeyDown, directory, "pttclick.wav");
63  this->updateEffect(CNotificationSounds::PTTClickKeyUp, directory, "pttclick.wav");
64 
65  // CNotificationSounds::AFVBlocked is generated
66  this->updateEffect(CNotificationSounds::AFVClicked, directory, Samples::fnClick());
67  }
68 
69  void CNotificationPlayer::onPlayingChanged()
70  {
71  if (!m_playingEffect) { return; }
72  if (m_playingEffect->isPlaying()) { return; }
73  m_playingEffect.clear();
74  }
75 
76  void CNotificationPlayer::updateEffect(CNotificationSounds::NotificationFlag f, const QString &directory,
77  const QString &name)
78  {
79  QSoundEffect *e = nullptr;
80  if (m_effects.contains(f)) { e = m_effects[f]; }
81  if (e) { e->deleteLater(); }
82 
83  // file if existing
84  const QUrl url = QUrl::fromLocalFile(CSwiftDirectories::soundFilePathOrDefaultPath(directory, name));
85  if (url.isEmpty() || !url.isLocalFile())
86  {
87  // remove notification as not existing
88  m_effects.remove(f);
89  return;
90  }
91 
92  // new effect
93  // QString fn = url.toLocalFile();
94  QSoundEffect *effect = new QSoundEffect(this);
95  effect->setSource(url);
96  effect->setLoopCount(1);
97  effect->setMuted(false);
98  m_effects[f] = effect;
99  connect(effect, &QSoundEffect::playingChanged, this, &CNotificationPlayer::onPlayingChanged,
100  Qt::QueuedConnection);
101  }
102 } // namespace swift::sound
Class for emitting a log message.
Definition: logmessage.h:27
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
void updateDirectory(const QString &directory)
Update the directory.
void play(swift::misc::audio::CNotificationSounds::NotificationFlag notification, int volume=100)
Play notification sound.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30