transmission/gtk/Notify.cc

256 lines
6.9 KiB
C++
Raw Normal View History

// This file Copyright © 2008-2022 Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <map>
#include <giomm.h>
#include <glibmm/i18n.h>
#include "Notify.h"
#include "Prefs.h"
#include "PrefsDialog.h"
#include "Session.h"
#include "Utils.h"
using namespace std::literals;
using StringVariantType = Glib::Variant<Glib::ustring>;
using StringListVariantType = Glib::Variant<std::vector<Glib::ustring>>;
using UInt32VariantType = Glib::Variant<guint32>;
namespace
{
auto const NotificationsDbusName = Glib::ustring("org.freedesktop.Notifications"s);
auto const NotificationsDbusCoreObject = Glib::ustring("/org/freedesktop/Notifications"s);
auto const NotificationsDbusCoreInterface = Glib::ustring("org.freedesktop.Notifications"s);
struct TrNotification
{
Glib::RefPtr<Session> core;
tr_torrent_id_t torrent_id = {};
};
Glib::RefPtr<Gio::DBus::Proxy> proxy;
std::map<guint32, TrNotification> active_notifications;
bool server_supports_actions = false;
template<typename... Ts>
Glib::VariantContainerBase make_variant_tuple(Ts&&... args)
{
return Glib::VariantContainerBase::create_tuple(
{ Glib::Variant<std::remove_cv_t<std::remove_reference_t<Ts>>>::create(std::forward<Ts>(args))... });
}
void get_capabilities_callback(Glib::RefPtr<Gio::AsyncResult>& res)
{
auto result = proxy->call_finish(res);
if (!result || result.get_n_children() != 1 || !result.get_child(0).is_of_type(StringListVariantType::variant_type()))
{
return;
}
auto const caps = Glib::VariantBase::cast_dynamic<StringListVariantType>(result.get_child(0)).get();
for (auto const& cap : caps)
{
if (cap == "actions")
{
server_supports_actions = true;
break;
}
}
}
void g_signal_callback(
Glib::ustring const& /*sender_name*/,
Glib::ustring const& signal_name,
Glib::VariantContainerBase params)
{
g_return_if_fail(params.get_n_children() > 0 && params.get_child(0).is_of_type(UInt32VariantType::variant_type()));
auto const id = Glib::VariantBase::cast_dynamic<UInt32VariantType>(params.get_child(0)).get();
auto const n_it = active_notifications.find(id);
if (n_it == active_notifications.end())
{
return;
}
auto const& n = n_it->second;
if (signal_name == "NotificationClosed")
{
active_notifications.erase(n_it);
}
else if (
signal_name == "ActionInvoked" && params.get_n_children() > 1 &&
params.get_child(1).is_of_type(StringVariantType::variant_type()))
{
auto const* tor = n.core->find_torrent(n.torrent_id);
if (tor == nullptr)
{
return;
}
auto const action = Glib::VariantBase::cast_dynamic<StringVariantType>(params.get_child(1)).get();
if (action == "folder")
{
n.core->open_folder(n.torrent_id);
}
else if (action == "file")
{
char const* dir = tr_torrentGetDownloadDir(tor);
auto const path = Glib::build_filename(dir, tr_torrentFile(tor, 0).name);
gtr_open_file(path);
}
else if (action == "start-now")
{
n.core->start_now(n.torrent_id);
}
}
}
void dbus_proxy_ready_callback(Glib::RefPtr<Gio::AsyncResult>& res)
{
proxy = Gio::DBus::Proxy::create_for_bus_finish(res);
if (proxy == nullptr)
{
g_warning("Failed to create proxy for %s", NotificationsDbusName.c_str());
return;
}
proxy->signal_signal().connect(&g_signal_callback);
proxy->call("GetCapabilities", &get_capabilities_callback);
}
} // namespace
void gtr_notify_init()
{
Gio::DBus::Proxy::create_for_bus(
Gio::DBus::BUS_TYPE_SESSION,
NotificationsDbusName,
NotificationsDbusCoreObject,
NotificationsDbusCoreInterface,
&dbus_proxy_ready_callback,
{},
Gio::DBus::PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES);
}
namespace
{
void notify_callback(Glib::RefPtr<Gio::AsyncResult>& res, TrNotification const& n)
{
auto result = proxy->call_finish(res);
if (!result || result.get_n_children() != 1 || !result.get_child(0).is_of_type(UInt32VariantType::variant_type()))
{
return;
}
auto const id = Glib::VariantBase::cast_dynamic<UInt32VariantType>(result.get_child(0)).get();
2022-01-17 18:39:50 +00:00
active_notifications.try_emplace(id, n);
}
} // namespace
void gtr_notify_torrent_completed(Glib::RefPtr<Session> const& core, tr_torrent_id_t tor_id)
{
if (gtr_pref_flag_get(TR_KEY_torrent_complete_sound_enabled))
{
auto const argv = gtr_pref_strv_get(TR_KEY_torrent_complete_sound_command);
try
{
Glib::spawn_async({}, argv, Glib::SPAWN_SEARCH_PATH);
}
catch (Glib::SpawnError const&)
{
}
}
if (!gtr_pref_flag_get(TR_KEY_torrent_complete_notification_enabled))
{
return;
}
g_return_if_fail(proxy != nullptr);
auto const* const tor = core->find_torrent(tor_id);
auto const n = TrNotification{ core, tor_id };
std::vector<Glib::ustring> actions;
if (server_supports_actions)
{
if (tr_torrentFileCount(tor) == 1)
{
fix: sonarcloud warnings (#2260) * fix: add-explicit-keyword-to-constructor warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuB-2farvsyMPiZl&open=AX1tyuB-2farvsyMPiZl * fix: use a structured binding declaration Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuHH2farvsyMPiZm&open=AX1tyuHH2farvsyMPiZm * Fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuH22farvsyMPiZn&open=AX1tyuH22farvsyMPiZn * fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZw&open=AX1tyuO42farvsyMPiZw * fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZs&open=AX1tyuO42farvsyMPiZs * fix: implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZt&open=AX1tyuO42farvsyMPiZt * fix handle-this-exceeption-or-do-not-catch-it warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpV&open=AX1y7t12cIz3krp3mVpV * fix make-this-variable-a-reference-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpW&open=AX1y7t12cIz3krp3mVpW * fix replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpY&open=AX1y7t12cIz3krp3mVpY * Fix use-try_emplace-instead-of-emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk3QwxvzFbF6whWN&open=AX0WPk3QwxvzFbF6whWN * Fix: make-this-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPUXjI_aUyxGBxB4&open=AX0bZPUXjI_aUyxGBxB4 * Fix use-std::make_unique warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk0twxvzFbF6whWC&open=AX0WPk0twxvzFbF6whWC * Fix: replace-push_back-with-emplace_back warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0BraL_0QLXO0pQ_Bfv&open=AX0BraL_0QLXO0pQ_Bfv * Fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB8&open=AX0bZPXajI_aUyxGBxB8 * Fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB9&open=AX0bZPXajI_aUyxGBxB9 * Fix: replace-emplace-with-try_emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB_&open=AX0bZPXajI_aUyxGBxB_ * Fix: extract-assignment-from-operation warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxCA&open=AX0bZPXajI_aUyxGBxCA * Fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1op6_hUBCnp-Grmra8&open=AX1op6_hUBCnp-Grmra8 * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0L8qgMUnpKTxYiu5CN&open=AX0L8qgMUnpKTxYiu5CN * Revert "Fix use-std::make_unique warning" This reverts commit 463a742f344e495416621825a7203d168f26343f. * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTZ&open=AX06St241usi2gyYkPTZ * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTa&open=AX06St241usi2gyYkPTa * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX01Itn2f_SST5i7BN1o&open=AX01Itn2f_SST5i7BN1o * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv55-MuQoG-Y-NgLX&open=AXziv55-MuQoG-Y-NgLX * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0_a_JGNJn7rAzml_68&open=AX0_a_JGNJn7rAzml_68 * fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXzyMRYbK9dvryvWm8XA&open=AXzyMRYbK9dvryvWm8XA * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv52fMuQoG-Y-NgLW&open=AXziv52fMuQoG-Y-NgLW
2021-12-01 23:11:57 +00:00
actions.emplace_back("file");
actions.emplace_back(_("Open File"));
}
else
{
fix: sonarcloud warnings (#2260) * fix: add-explicit-keyword-to-constructor warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuB-2farvsyMPiZl&open=AX1tyuB-2farvsyMPiZl * fix: use a structured binding declaration Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuHH2farvsyMPiZm&open=AX1tyuHH2farvsyMPiZm * Fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuH22farvsyMPiZn&open=AX1tyuH22farvsyMPiZn * fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZw&open=AX1tyuO42farvsyMPiZw * fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZs&open=AX1tyuO42farvsyMPiZs * fix: implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZt&open=AX1tyuO42farvsyMPiZt * fix handle-this-exceeption-or-do-not-catch-it warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpV&open=AX1y7t12cIz3krp3mVpV * fix make-this-variable-a-reference-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpW&open=AX1y7t12cIz3krp3mVpW * fix replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpY&open=AX1y7t12cIz3krp3mVpY * Fix use-try_emplace-instead-of-emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk3QwxvzFbF6whWN&open=AX0WPk3QwxvzFbF6whWN * Fix: make-this-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPUXjI_aUyxGBxB4&open=AX0bZPUXjI_aUyxGBxB4 * Fix use-std::make_unique warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk0twxvzFbF6whWC&open=AX0WPk0twxvzFbF6whWC * Fix: replace-push_back-with-emplace_back warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0BraL_0QLXO0pQ_Bfv&open=AX0BraL_0QLXO0pQ_Bfv * Fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB8&open=AX0bZPXajI_aUyxGBxB8 * Fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB9&open=AX0bZPXajI_aUyxGBxB9 * Fix: replace-emplace-with-try_emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB_&open=AX0bZPXajI_aUyxGBxB_ * Fix: extract-assignment-from-operation warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxCA&open=AX0bZPXajI_aUyxGBxCA * Fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1op6_hUBCnp-Grmra8&open=AX1op6_hUBCnp-Grmra8 * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0L8qgMUnpKTxYiu5CN&open=AX0L8qgMUnpKTxYiu5CN * Revert "Fix use-std::make_unique warning" This reverts commit 463a742f344e495416621825a7203d168f26343f. * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTZ&open=AX06St241usi2gyYkPTZ * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTa&open=AX06St241usi2gyYkPTa * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX01Itn2f_SST5i7BN1o&open=AX01Itn2f_SST5i7BN1o * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv55-MuQoG-Y-NgLX&open=AXziv55-MuQoG-Y-NgLX * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0_a_JGNJn7rAzml_68&open=AX0_a_JGNJn7rAzml_68 * fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXzyMRYbK9dvryvWm8XA&open=AXzyMRYbK9dvryvWm8XA * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv52fMuQoG-Y-NgLW&open=AXziv52fMuQoG-Y-NgLW
2021-12-01 23:11:57 +00:00
actions.emplace_back("folder");
actions.emplace_back(_("Open Folder"));
}
}
std::map<Glib::ustring, Glib::VariantBase> hints;
2022-01-17 18:39:50 +00:00
hints.try_emplace("category", StringVariantType::create("transfer.complete"));
proxy->call(
"Notify",
[n](auto& res) { notify_callback(res, n); },
make_variant_tuple(
Glib::ustring("Transmission"),
0u,
Glib::ustring("transmission"),
Glib::ustring(_("Torrent Complete")),
Glib::ustring(tr_torrentName(tor)),
actions,
hints,
-1));
}
void gtr_notify_torrent_added(Glib::RefPtr<Session> const& core, tr_torrent_id_t tor_id)
{
g_return_if_fail(proxy != nullptr);
if (!gtr_pref_flag_get(TR_KEY_torrent_added_notification_enabled))
{
return;
}
auto const* const tor = core->find_torrent(tor_id);
std::vector<Glib::ustring> actions;
if (server_supports_actions)
{
fix: sonarcloud warnings (#2260) * fix: add-explicit-keyword-to-constructor warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuB-2farvsyMPiZl&open=AX1tyuB-2farvsyMPiZl * fix: use a structured binding declaration Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuHH2farvsyMPiZm&open=AX1tyuHH2farvsyMPiZm * Fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuH22farvsyMPiZn&open=AX1tyuH22farvsyMPiZn * fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZw&open=AX1tyuO42farvsyMPiZw * fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZs&open=AX1tyuO42farvsyMPiZs * fix: implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZt&open=AX1tyuO42farvsyMPiZt * fix handle-this-exceeption-or-do-not-catch-it warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpV&open=AX1y7t12cIz3krp3mVpV * fix make-this-variable-a-reference-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpW&open=AX1y7t12cIz3krp3mVpW * fix replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpY&open=AX1y7t12cIz3krp3mVpY * Fix use-try_emplace-instead-of-emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk3QwxvzFbF6whWN&open=AX0WPk3QwxvzFbF6whWN * Fix: make-this-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPUXjI_aUyxGBxB4&open=AX0bZPUXjI_aUyxGBxB4 * Fix use-std::make_unique warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk0twxvzFbF6whWC&open=AX0WPk0twxvzFbF6whWC * Fix: replace-push_back-with-emplace_back warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0BraL_0QLXO0pQ_Bfv&open=AX0BraL_0QLXO0pQ_Bfv * Fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB8&open=AX0bZPXajI_aUyxGBxB8 * Fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB9&open=AX0bZPXajI_aUyxGBxB9 * Fix: replace-emplace-with-try_emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB_&open=AX0bZPXajI_aUyxGBxB_ * Fix: extract-assignment-from-operation warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxCA&open=AX0bZPXajI_aUyxGBxCA * Fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1op6_hUBCnp-Grmra8&open=AX1op6_hUBCnp-Grmra8 * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0L8qgMUnpKTxYiu5CN&open=AX0L8qgMUnpKTxYiu5CN * Revert "Fix use-std::make_unique warning" This reverts commit 463a742f344e495416621825a7203d168f26343f. * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTZ&open=AX06St241usi2gyYkPTZ * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTa&open=AX06St241usi2gyYkPTa * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX01Itn2f_SST5i7BN1o&open=AX01Itn2f_SST5i7BN1o * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv55-MuQoG-Y-NgLX&open=AXziv55-MuQoG-Y-NgLX * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0_a_JGNJn7rAzml_68&open=AX0_a_JGNJn7rAzml_68 * fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXzyMRYbK9dvryvWm8XA&open=AXzyMRYbK9dvryvWm8XA * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv52fMuQoG-Y-NgLW&open=AXziv52fMuQoG-Y-NgLW
2021-12-01 23:11:57 +00:00
actions.emplace_back("start-now");
actions.emplace_back(_("Start Now"));
}
auto const n = TrNotification{ core, tor_id };
proxy->call(
"Notify",
[n](auto& res) { notify_callback(res, n); },
make_variant_tuple(
Glib::ustring("Transmission"),
0u,
Glib::ustring("transmission"),
Glib::ustring(_("Torrent Added")),
Glib::ustring(tr_torrentName(tor)),
actions,
std::map<Glib::ustring, Glib::VariantBase>(),
-1));
}