tdlight/td/telegram/NotificationSound.cpp

317 lines
11 KiB
C++

//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// 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"
#include "td/utils/logging.h"
#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> &notification_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> &notification_sound, LogEventParser &parser) {
parse(notification_sound, parser);
}
StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr<NotificationSound> &notification_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> &notification_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> &notification_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);
}
unique_ptr<NotificationSound> get_notification_sound(telegram_api::NotificationSound *notification_sound) {
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) {
LOG(ERROR) << "Receive ringtone with ID = " << sound->id_;
return make_unique<NotificationSoundNone>();
}
return td::make_unique<NotificationSoundRingtone>(sound->id_);
}
default:
UNREACHABLE();
return nullptr;
}
}
unique_ptr<NotificationSound> get_notification_sound(telegram_api::peerNotifySettings *settings, bool for_stories) {
CHECK(settings != nullptr);
telegram_api::NotificationSound *sound =
#if TD_ANDROID
for_stories ? settings->stories_android_sound_.get() : settings->android_sound_.get();
#elif TD_DARWIN_IOS || TD_DARWIN_TV_OS || TD_DARWIN_VISION_OS || TD_DARWIN_WATCH_OS || TD_DARWIN_UNKNOWN
for_stories ? settings->stories_ios_sound_.get() : settings->ios_sound_.get();
#else
for_stories ? settings->stories_other_sound_.get() : settings->other_sound_.get();
#endif
return get_notification_sound(sound);
}
telegram_api::object_ptr<telegram_api::NotificationSound> get_input_notification_sound(
const unique_ptr<NotificationSound> &notification_sound, bool return_non_null) {
if (notification_sound == nullptr) {
if (return_non_null) {
return telegram_api::make_object<telegram_api::notificationSoundDefault>();
}
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> &notification_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