2022-04-11 19:01:44 +02:00
|
|
|
//
|
2024-01-01 01:07:21 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
2022-04-11 19:01:44 +02:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#include "td/telegram/NotificationSound.h"
|
|
|
|
|
2022-06-02 15:19:16 +02:00
|
|
|
#include "td/utils/logging.h"
|
2022-04-11 19:01:44 +02:00
|
|
|
#include "td/utils/tl_helpers.h"
|
|
|
|
|
|
|
|
namespace td {
|
|
|
|
|
|
|
|
class NotificationSoundNone final : public NotificationSound {
|
|
|
|
public:
|
|
|
|
NotificationSoundNone() = default;
|
|
|
|
|
|
|
|
NotificationSoundType get_type() const final {
|
|
|
|
return NotificationSoundType::None;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class NotificationSoundLocal final : public NotificationSound {
|
|
|
|
public:
|
|
|
|
string title_;
|
|
|
|
string data_;
|
|
|
|
|
|
|
|
NotificationSoundLocal() = default;
|
|
|
|
NotificationSoundLocal(string title, string data) : title_(std::move(title)), data_(std::move(data)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
NotificationSoundType get_type() const final {
|
|
|
|
return NotificationSoundType::Local;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class NotificationSoundRingtone final : public NotificationSound {
|
|
|
|
public:
|
|
|
|
int64 ringtone_id_;
|
|
|
|
|
|
|
|
NotificationSoundRingtone() = default;
|
|
|
|
explicit NotificationSoundRingtone(int64 ringtone_id) : ringtone_id_(ringtone_id) {
|
|
|
|
}
|
|
|
|
|
|
|
|
NotificationSoundType get_type() const final {
|
|
|
|
return NotificationSoundType::Ringtone;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class StorerT>
|
|
|
|
static void store(const NotificationSound *notification_sound, StorerT &storer) {
|
|
|
|
CHECK(notification_sound != nullptr);
|
|
|
|
|
|
|
|
auto sound_type = notification_sound->get_type();
|
|
|
|
store(sound_type, storer);
|
|
|
|
|
|
|
|
switch (sound_type) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
break;
|
|
|
|
case NotificationSoundType::Local: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound);
|
|
|
|
store(sound->title_, storer);
|
|
|
|
store(sound->data_, storer);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NotificationSoundType::Ringtone: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound);
|
|
|
|
store(sound->ringtone_id_, storer);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ParserT>
|
|
|
|
static void parse(unique_ptr<NotificationSound> ¬ification_sound, ParserT &parser) {
|
|
|
|
NotificationSoundType sound_type;
|
|
|
|
parse(sound_type, parser);
|
|
|
|
|
|
|
|
switch (sound_type) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
notification_sound = make_unique<NotificationSoundNone>();
|
|
|
|
break;
|
|
|
|
case NotificationSoundType::Local: {
|
|
|
|
auto sound = make_unique<NotificationSoundLocal>();
|
|
|
|
parse(sound->title_, parser);
|
|
|
|
parse(sound->data_, parser);
|
|
|
|
notification_sound = std::move(sound);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NotificationSoundType::Ringtone: {
|
|
|
|
auto sound = make_unique<NotificationSoundRingtone>();
|
|
|
|
parse(sound->ringtone_id_, parser);
|
|
|
|
notification_sound = std::move(sound);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
LOG(FATAL) << "Have unknown notification sound type " << static_cast<int32>(sound_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void store_notification_sound(const NotificationSound *notification_sound, LogEventStorerCalcLength &storer) {
|
|
|
|
store(notification_sound, storer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void store_notification_sound(const NotificationSound *notification_sound, LogEventStorerUnsafe &storer) {
|
|
|
|
store(notification_sound, storer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void parse_notification_sound(unique_ptr<NotificationSound> ¬ification_sound, LogEventParser &parser) {
|
|
|
|
parse(notification_sound, parser);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr<NotificationSound> ¬ification_sound) {
|
|
|
|
if (notification_sound == nullptr) {
|
|
|
|
return string_builder << "DefaultSound";
|
|
|
|
}
|
|
|
|
switch (notification_sound->get_type()) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
return string_builder << "NoSound";
|
|
|
|
case NotificationSoundType::Local: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound.get());
|
|
|
|
return string_builder << "LocalSound[" << sound->title_ << '|' << sound->data_ << ']';
|
|
|
|
}
|
|
|
|
case NotificationSoundType::Ringtone: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound.get());
|
|
|
|
return string_builder << "Ringtone[" << sound->ringtone_id_ << ']';
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
return string_builder;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_notification_sound_default(const unique_ptr<NotificationSound> ¬ification_sound) {
|
|
|
|
if (notification_sound == nullptr) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return notification_sound->get_type() == NotificationSoundType::Local;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool are_equivalent_notification_sounds(const unique_ptr<NotificationSound> &lhs,
|
|
|
|
const unique_ptr<NotificationSound> &rhs) {
|
|
|
|
if (is_notification_sound_default(lhs)) {
|
|
|
|
return is_notification_sound_default(rhs);
|
|
|
|
}
|
|
|
|
if (is_notification_sound_default(rhs)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto sound_type = lhs->get_type();
|
|
|
|
if (sound_type != rhs->get_type()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (sound_type) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
return true;
|
|
|
|
case NotificationSoundType::Ringtone:
|
|
|
|
return static_cast<const NotificationSoundRingtone *>(lhs.get())->ringtone_id_ ==
|
|
|
|
static_cast<const NotificationSoundRingtone *>(rhs.get())->ringtone_id_;
|
|
|
|
case NotificationSoundType::Local:
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool are_different_equivalent_notification_sounds(const unique_ptr<NotificationSound> &lhs,
|
|
|
|
const unique_ptr<NotificationSound> &rhs) {
|
|
|
|
if (lhs == nullptr) {
|
|
|
|
return rhs != nullptr && rhs->get_type() == NotificationSoundType::Local;
|
|
|
|
}
|
|
|
|
if (rhs == nullptr) {
|
|
|
|
return lhs->get_type() == NotificationSoundType::Local;
|
|
|
|
}
|
|
|
|
if (lhs->get_type() != NotificationSoundType::Local || rhs->get_type() != NotificationSoundType::Local) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto *lhs_local = static_cast<const NotificationSoundLocal *>(lhs.get());
|
|
|
|
const auto *rhs_local = static_cast<const NotificationSoundLocal *>(rhs.get());
|
|
|
|
return lhs_local->title_ != rhs_local->title_ || lhs_local->data_ != rhs_local->data_;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64 get_notification_sound_ringtone_id(const unique_ptr<NotificationSound> ¬ification_sound) {
|
|
|
|
if (notification_sound == nullptr) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
switch (notification_sound->get_type()) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
return 0;
|
|
|
|
case NotificationSoundType::Local:
|
|
|
|
return -1;
|
|
|
|
case NotificationSoundType::Ringtone: {
|
|
|
|
return static_cast<const NotificationSoundRingtone *>(notification_sound.get())->ringtone_id_;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<NotificationSound> get_legacy_notification_sound(const string &sound) {
|
|
|
|
if (sound == "default") {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (sound.empty()) {
|
|
|
|
return make_unique<NotificationSoundNone>();
|
|
|
|
}
|
|
|
|
return td::make_unique<NotificationSoundLocal>(sound, sound);
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<NotificationSound> get_notification_sound(bool use_default_sound, int64 ringtone_id) {
|
|
|
|
if (use_default_sound || ringtone_id == -1) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (ringtone_id == 0) {
|
|
|
|
return make_unique<NotificationSoundNone>();
|
|
|
|
}
|
|
|
|
return td::make_unique<NotificationSoundRingtone>(ringtone_id);
|
|
|
|
}
|
|
|
|
|
2024-04-24 15:30:07 +02:00
|
|
|
unique_ptr<NotificationSound> get_notification_sound(telegram_api::NotificationSound *notification_sound) {
|
2022-04-11 19:01:44 +02:00
|
|
|
if (notification_sound == nullptr) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (notification_sound->get_id()) {
|
|
|
|
case telegram_api::notificationSoundDefault::ID:
|
|
|
|
return nullptr;
|
|
|
|
case telegram_api::notificationSoundNone::ID:
|
|
|
|
return make_unique<NotificationSoundNone>();
|
|
|
|
case telegram_api::notificationSoundLocal::ID: {
|
|
|
|
const auto *sound = static_cast<telegram_api::notificationSoundLocal *>(notification_sound);
|
|
|
|
return td::make_unique<NotificationSoundLocal>(std::move(sound->title_), std::move(sound->data_));
|
|
|
|
}
|
|
|
|
case telegram_api::notificationSoundRingtone::ID: {
|
|
|
|
const auto *sound = static_cast<telegram_api::notificationSoundRingtone *>(notification_sound);
|
|
|
|
if (sound->id_ == 0 || sound->id_ == -1) {
|
2022-06-02 15:19:16 +02:00
|
|
|
LOG(ERROR) << "Receive ringtone with ID = " << sound->id_;
|
2022-04-11 19:01:44 +02:00
|
|
|
return make_unique<NotificationSoundNone>();
|
|
|
|
}
|
|
|
|
return td::make_unique<NotificationSoundRingtone>(sound->id_);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-27 17:30:05 +02:00
|
|
|
unique_ptr<NotificationSound> get_notification_sound(telegram_api::peerNotifySettings *settings, bool for_stories) {
|
2022-10-25 00:22:04 +02:00
|
|
|
CHECK(settings != nullptr);
|
|
|
|
telegram_api::NotificationSound *sound =
|
|
|
|
#if TD_ANDROID
|
2023-06-27 17:30:05 +02:00
|
|
|
for_stories ? settings->stories_android_sound_.get() : settings->android_sound_.get();
|
2024-03-11 20:47:54 +01:00
|
|
|
#elif TD_DARWIN_IOS || TD_DARWIN_TV_OS || TD_DARWIN_VISION_OS || TD_DARWIN_WATCH_OS || TD_DARWIN_UNKNOWN
|
2023-06-27 17:30:05 +02:00
|
|
|
for_stories ? settings->stories_ios_sound_.get() : settings->ios_sound_.get();
|
2022-10-25 00:22:04 +02:00
|
|
|
#else
|
2023-06-27 17:30:05 +02:00
|
|
|
for_stories ? settings->stories_other_sound_.get() : settings->other_sound_.get();
|
2022-10-25 00:22:04 +02:00
|
|
|
#endif
|
|
|
|
return get_notification_sound(sound);
|
|
|
|
}
|
|
|
|
|
2022-04-11 19:01:44 +02:00
|
|
|
telegram_api::object_ptr<telegram_api::NotificationSound> get_input_notification_sound(
|
2024-04-24 15:30:07 +02:00
|
|
|
const unique_ptr<NotificationSound> ¬ification_sound, bool return_non_null) {
|
2022-04-11 19:01:44 +02:00
|
|
|
if (notification_sound == nullptr) {
|
2024-04-24 15:30:07 +02:00
|
|
|
if (return_non_null) {
|
|
|
|
return telegram_api::make_object<telegram_api::notificationSoundDefault>();
|
|
|
|
}
|
2022-04-11 19:01:44 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// must not return nullptr if notification_sound != nullptr
|
|
|
|
switch (notification_sound->get_type()) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
return telegram_api::make_object<telegram_api::notificationSoundNone>();
|
|
|
|
case NotificationSoundType::Local: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound.get());
|
|
|
|
return telegram_api::make_object<telegram_api::notificationSoundLocal>(sound->title_, sound->data_);
|
|
|
|
}
|
|
|
|
case NotificationSoundType::Ringtone: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound.get());
|
|
|
|
return telegram_api::make_object<telegram_api::notificationSoundRingtone>(sound->ringtone_id_);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<NotificationSound> dup_notification_sound(const unique_ptr<NotificationSound> ¬ification_sound) {
|
|
|
|
if (notification_sound == nullptr) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (notification_sound->get_type()) {
|
|
|
|
case NotificationSoundType::None:
|
|
|
|
return make_unique<NotificationSoundNone>();
|
|
|
|
case NotificationSoundType::Local: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound.get());
|
|
|
|
return td::make_unique<NotificationSoundLocal>(sound->title_, sound->data_);
|
|
|
|
}
|
|
|
|
case NotificationSoundType::Ringtone: {
|
|
|
|
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound.get());
|
|
|
|
return td::make_unique<NotificationSoundRingtone>(sound->ringtone_id_);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace td
|