timers work, fix crash when vscode window closes after timeout
This commit is contained in:
@@ -67,7 +67,7 @@ class Timer : public Gtk::Box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void activateTimer() {
|
void activateTimer() {
|
||||||
std::cout << "Timer activated" << std::endl;
|
// std::cout << "Timer activated" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTimeLeft(uint64_t timeValue) {
|
void updateTimeLeft(uint64_t timeValue) {
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ class StringHelper {
|
|||||||
if (input.length() <= maxSize) {
|
if (input.length() <= maxSize) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
return input.substr(0, maxSize) + "...";
|
|
||||||
|
size_t len = maxSize;
|
||||||
|
while (len > 0 && (static_cast<unsigned char>(input[len]) & 0xC0) == 0x80) {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input.substr(0, len) + "...";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "glibmm/main.h"
|
#include "glibmm/main.h"
|
||||||
|
#include "gtkmm/mediafile.h"
|
||||||
|
#include "gtkmm/mediastream.h"
|
||||||
#include "sigc++/signal.h"
|
#include "sigc++/signal.h"
|
||||||
class TimerService {
|
class TimerService {
|
||||||
struct TimerData {
|
struct TimerData {
|
||||||
@@ -15,7 +18,7 @@ class TimerService {
|
|||||||
public:
|
public:
|
||||||
static std::shared_ptr<TimerService> getInstance() {
|
static std::shared_ptr<TimerService> getInstance() {
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = std::make_shared<TimerService>();
|
instance = std::shared_ptr<TimerService>(new TimerService());
|
||||||
|
|
||||||
// add a timer to tick every second
|
// add a timer to tick every second
|
||||||
Glib::signal_timeout().connect([]() {
|
Glib::signal_timeout().connect([]() {
|
||||||
@@ -37,11 +40,28 @@ class TimerService {
|
|||||||
|
|
||||||
void expireTimer(uint64_t timerId) {
|
void expireTimer(uint64_t timerId) {
|
||||||
this->timerExpiredSignal.emit(timerId);
|
this->timerExpiredSignal.emit(timerId);
|
||||||
|
|
||||||
|
if (ringingTimerCounter == 0) {
|
||||||
|
mediaFile->set_volume(1.0);
|
||||||
|
mediaFile->set_loop(true);
|
||||||
|
mediaFile->play();
|
||||||
|
spdlog::info("Playing timer sound");
|
||||||
|
}
|
||||||
|
|
||||||
|
ringingTimerCounter++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeTimer(uint64_t timerId) {
|
void removeTimer(uint64_t timerId) {
|
||||||
|
ringingTimerCounter--;
|
||||||
this->activeTimers.erase(timerId);
|
this->activeTimers.erase(timerId);
|
||||||
this->timerCancelledSignal.emit(timerId);
|
this->timerCancelledSignal.emit(timerId);
|
||||||
|
|
||||||
|
if (ringingTimerCounter <= 0) {
|
||||||
|
ringingTimerCounter = 0;
|
||||||
|
mediaFile->pause();
|
||||||
|
spdlog::info("Paused timer sound");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sigc::signal<void(const std::string &, u_int64_t)> &getSignalTimerSet() {
|
sigc::signal<void(const std::string &, u_int64_t)> &getSignalTimerSet() {
|
||||||
@@ -59,7 +79,32 @@ class TimerService {
|
|||||||
sigc::signal<void()> tickSignal;
|
sigc::signal<void()> tickSignal;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static inline uint64_t timerIdCounter = 0;
|
TimerService() {
|
||||||
|
this->mediaFile = Gtk::MediaFile::create();
|
||||||
|
if (this->mediaFile) {
|
||||||
|
this->mediaFile->set_filename("/usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga");
|
||||||
|
|
||||||
|
// Connect to signals to debug playback issues
|
||||||
|
this->mediaFile->property_error().signal_changed().connect([]() {
|
||||||
|
if (auto err = mediaFile->get_error()) {
|
||||||
|
spdlog::error("Timer sound error: {}", err.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this->mediaFile->property_prepared().signal_changed().connect([]() {
|
||||||
|
if (mediaFile->is_prepared()) {
|
||||||
|
spdlog::info("Timer sound ready");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
spdlog::error("Failed to create media file!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static Glib::RefPtr<Gtk::MediaFile> mediaFile;
|
||||||
|
|
||||||
|
static inline uint64_t timerIdCounter = 0;
|
||||||
|
static inline u_int64_t ringingTimerCounter = 0;
|
||||||
sigc::signal<void(const std::string &, u_int64_t)> timerAddedSignal;
|
sigc::signal<void(const std::string &, u_int64_t)> timerAddedSignal;
|
||||||
sigc::signal<void(u_int64_t)> timerCancelledSignal;
|
sigc::signal<void(u_int64_t)> timerCancelledSignal;
|
||||||
sigc::signal<void(u_int64_t)> timerExpiredSignal;
|
sigc::signal<void(u_int64_t)> timerExpiredSignal;
|
||||||
@@ -73,6 +118,7 @@ class TimerService {
|
|||||||
if (timer.duration > 0) {
|
if (timer.duration > 0) {
|
||||||
timer.duration--;
|
timer.duration--;
|
||||||
} else if (timer.duration == 0) {
|
} else if (timer.duration == 0) {
|
||||||
|
spdlog::info("Timer {} expired", timer.timerId);
|
||||||
expireTimer(timer.timerId);
|
expireTimer(timer.timerId);
|
||||||
timer.duration = -1; // Mark as expired to prevent multiple expirations
|
timer.duration = -1; // Mark as expired to prevent multiple expirations
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <sigc++/connection.h>
|
#include <sigc++/connection.h>
|
||||||
|
|
||||||
#include "gdkmm/monitor.h"
|
#include "gdkmm/monitor.h"
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
|
|
||||||
#define DEFAULT_NOTIFICATION_TIMEOUT 6700
|
#define DEFAULT_NOTIFICATION_TIMEOUT 6700
|
||||||
|
|
||||||
class BaseNotification : public Gtk::Window {
|
class BaseNotification : public Gtk::Window, public std::enable_shared_from_this<BaseNotification> {
|
||||||
public:
|
public:
|
||||||
BaseNotification(uint64_t notificationId, std::shared_ptr<Gdk::Monitor> monitor);
|
BaseNotification(uint64_t notificationId, std::shared_ptr<Gdk::Monitor> monitor);
|
||||||
|
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ void BaseNotification::start_auto_close_timeout(int timeoutMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
autoCloseDeadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs);
|
autoCloseDeadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs);
|
||||||
autoCloseConnection = Glib::signal_timeout().connect([this]() {
|
autoCloseConnection = Glib::signal_timeout().connect([self = shared_from_this()]() {
|
||||||
this->getSignalClose().emit(this->notificationId);
|
self->getSignalClose().emit(self->getNotificationId());
|
||||||
return false; // Don't repeat
|
return false; // Don't repeat
|
||||||
},
|
},
|
||||||
timeoutMs);
|
timeoutMs);
|
||||||
|
|||||||
@@ -44,23 +44,29 @@ NotificationWindow::NotificationWindow(uint64_t notificationId, std::shared_ptr<
|
|||||||
header_box->append(*img);
|
header_box->append(*img);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto app_label = Gtk::make_managed<Gtk::Label>(StringHelper::trimToSize(notify.app_name, 24));
|
auto app_label = Gtk::make_managed<Gtk::Label>(notify.app_name);
|
||||||
app_label->set_halign(Gtk::Align::START);
|
app_label->set_halign(Gtk::Align::START);
|
||||||
|
app_label->set_ellipsize(Pango::EllipsizeMode::END);
|
||||||
|
app_label->set_max_width_chars(24);
|
||||||
app_label->set_wrap(false);
|
app_label->set_wrap(false);
|
||||||
app_label->add_css_class("notification-app-name");
|
app_label->add_css_class("notification-app-name");
|
||||||
header_box->append(*app_label);
|
header_box->append(*app_label);
|
||||||
vbox->append(*header_box);
|
vbox->append(*header_box);
|
||||||
|
|
||||||
// Summary label
|
// Summary label
|
||||||
auto summary_label = Gtk::make_managed<Gtk::Label>("<b>" + StringHelper::trimToSize(notify.summary, 20) + "</b>");
|
auto summary_label = Gtk::make_managed<Gtk::Label>("<b>" + notify.summary + "</b>");
|
||||||
summary_label->set_use_markup(true);
|
summary_label->set_use_markup(true);
|
||||||
summary_label->set_halign(Gtk::Align::START);
|
summary_label->set_halign(Gtk::Align::START);
|
||||||
|
summary_label->set_ellipsize(Pango::EllipsizeMode::END);
|
||||||
|
summary_label->set_lines(1);
|
||||||
summary_label->set_wrap(true);
|
summary_label->set_wrap(true);
|
||||||
vbox->append(*summary_label);
|
vbox->append(*summary_label);
|
||||||
|
|
||||||
auto body_label = Gtk::make_managed<Gtk::Label>(StringHelper::trimToSize(notify.body, 100));
|
auto body_label = Gtk::make_managed<Gtk::Label>(notify.body);
|
||||||
body_label->set_use_markup(true);
|
body_label->set_use_markup(true);
|
||||||
body_label->set_halign(Gtk::Align::START);
|
body_label->set_halign(Gtk::Align::START);
|
||||||
|
body_label->set_ellipsize(Pango::EllipsizeMode::END);
|
||||||
|
body_label->set_lines(3);
|
||||||
body_label->set_wrap(true);
|
body_label->set_wrap(true);
|
||||||
vbox->append(*body_label);
|
vbox->append(*body_label);
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,12 @@ SpotifyNotification::SpotifyNotification(uint64_t notificationId, std::shared_pt
|
|||||||
|
|
||||||
auto artistLabel = Gtk::make_managed<Gtk::Label>();
|
auto artistLabel = Gtk::make_managed<Gtk::Label>();
|
||||||
if (!mpris.artist.empty()) {
|
if (!mpris.artist.empty()) {
|
||||||
artistLabel->set_text(StringHelper::trimToSize(mpris.artist[0], 30));
|
artistLabel->set_text(mpris.artist[0]);
|
||||||
} else {
|
} else {
|
||||||
artistLabel->set_text("Unknown Artist");
|
artistLabel->set_text("Unknown Artist");
|
||||||
}
|
}
|
||||||
|
artistLabel->set_ellipsize(Pango::EllipsizeMode::END);
|
||||||
|
artistLabel->set_max_width_chars(30);
|
||||||
artistLabel->set_hexpand(true);
|
artistLabel->set_hexpand(true);
|
||||||
artistLabel->set_halign(Gtk::Align::CENTER);
|
artistLabel->set_halign(Gtk::Align::CENTER);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user