// // 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 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(notification_sound); store(sound->title_, storer); store(sound->data_, storer); break; } case NotificationSoundType::Ringtone: { const auto *sound = static_cast(notification_sound); store(sound->ringtone_id_, storer); break; } default: UNREACHABLE(); } } template static void parse(unique_ptr ¬ification_sound, ParserT &parser) { NotificationSoundType sound_type; parse(sound_type, parser); switch (sound_type) { case NotificationSoundType::None: notification_sound = make_unique(); break; case NotificationSoundType::Local: { auto sound = make_unique(); parse(sound->title_, parser); parse(sound->data_, parser); notification_sound = std::move(sound); break; } case NotificationSoundType::Ringtone: { auto sound = make_unique(); parse(sound->ringtone_id_, parser); notification_sound = std::move(sound); break; } default: LOG(FATAL) << "Have unknown notification sound type " << static_cast(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 ¬ification_sound, LogEventParser &parser) { parse(notification_sound, parser); } StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr ¬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(notification_sound.get()); return string_builder << "LocalSound[" << sound->title_ << '|' << sound->data_ << ']'; } case NotificationSoundType::Ringtone: { const auto *sound = static_cast(notification_sound.get()); return string_builder << "Ringtone[" << sound->ringtone_id_ << ']'; } default: UNREACHABLE(); return string_builder; } } bool is_notification_sound_default(const unique_ptr ¬ification_sound) { if (notification_sound == nullptr) { return true; } return notification_sound->get_type() == NotificationSoundType::Local; } bool are_equivalent_notification_sounds(const unique_ptr &lhs, const unique_ptr &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(lhs.get())->ringtone_id_ == static_cast(rhs.get())->ringtone_id_; case NotificationSoundType::Local: default: UNREACHABLE(); break; } return false; } bool are_different_equivalent_notification_sounds(const unique_ptr &lhs, const unique_ptr &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(lhs.get()); const auto *rhs_local = static_cast(rhs.get()); return lhs_local->title_ != rhs_local->title_ || lhs_local->data_ != rhs_local->data_; } int64 get_notification_sound_ringtone_id(const unique_ptr ¬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(notification_sound.get())->ringtone_id_; default: UNREACHABLE(); return -1; } } } unique_ptr get_legacy_notification_sound(const string &sound) { if (sound == "default") { return nullptr; } if (sound.empty()) { return make_unique(); } return td::make_unique(sound, sound); } unique_ptr 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(); } return td::make_unique(ringtone_id); } static unique_ptr 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(); case telegram_api::notificationSoundLocal::ID: { const auto *sound = static_cast(notification_sound); return td::make_unique(std::move(sound->title_), std::move(sound->data_)); } case telegram_api::notificationSoundRingtone::ID: { const auto *sound = static_cast(notification_sound); if (sound->id_ == 0 || sound->id_ == -1) { LOG(ERROR) << "Receive ringtone with ID = " << sound->id_; return make_unique(); } return td::make_unique(sound->id_); } default: UNREACHABLE(); return nullptr; } } unique_ptr 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 get_input_notification_sound( const unique_ptr ¬ification_sound) { if (notification_sound == nullptr) { return nullptr; } // must not return nullptr if notification_sound != nullptr switch (notification_sound->get_type()) { case NotificationSoundType::None: return telegram_api::make_object(); case NotificationSoundType::Local: { const auto *sound = static_cast(notification_sound.get()); return telegram_api::make_object(sound->title_, sound->data_); } case NotificationSoundType::Ringtone: { const auto *sound = static_cast(notification_sound.get()); return telegram_api::make_object(sound->ringtone_id_); } default: UNREACHABLE(); return nullptr; } } unique_ptr dup_notification_sound(const unique_ptr ¬ification_sound) { if (notification_sound == nullptr) { return nullptr; } switch (notification_sound->get_type()) { case NotificationSoundType::None: return make_unique(); case NotificationSoundType::Local: { const auto *sound = static_cast(notification_sound.get()); return td::make_unique(sound->title_, sound->data_); } case NotificationSoundType::Ringtone: { const auto *sound = static_cast(notification_sound.get()); return td::make_unique(sound->ringtone_id_); } default: UNREACHABLE(); return nullptr; } } } // namespace td