#include "Ecore.h"
#include "ecore_private.h"
+#ifdef USE_TIZEN_CORE
+#include "tizen-core/tcore_timer.h"
+#endif // USE_TIZEN_CORE
+
+
#define MY_CLASS EFL_LOOP_TIMER_CLASS
#define MY_CLASS_NAME "Efl_Loop_Timer"
EAPI Ecore_Timer *
ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ if (in < 0.05f) in = 0.05f;
+ return tcore_timer_add(in * 1000, func, data);
+ }
+#endif // USE_TIZEN_CORE
+
Ecore_Timer_Legacy *legacy;
Eo *timer;
EAPI Ecore_Timer *
ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ if (in < 0.05f) in = 0.05f;
+ return tcore_timer_add(in * 1000, func, data);
+ }
+#endif // USE_TIZEN_CORE
+
Ecore_Timer_Legacy *legacy;
Eo *timer;
EAPI void *
ecore_timer_del(Ecore_Timer *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ return tcore_timer_del(timer);
+ }
+#endif // USE_TIZEN_CORE
+
void *data;
if (!timer) return NULL;
EOLIAN static void
_efl_loop_timer_timer_interval_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer, double in)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ if (in < 0.05f) in = 0.05f;
+ tcore_timer_set_interval(timer, in * 1000);
+ return;
+ }
+#endif // USE_TIZEN_CORE
+
if (in < 0.0) in = 0.0;
timer->in = in;
}
EOLIAN static double
_efl_loop_timer_timer_interval_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ double ret = tcore_timer_get_interval(timer);
+
+ return ret / 1000.0;
+ }
+#endif // USE_TIZEN_CORE
+
return timer->in;
}
EOLIAN static void
_efl_loop_timer_timer_delay(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, double add)
{
+ #ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ tcore_timer_set_delay(pd, add * 1000);
+ return;
+ }
+#endif // USE_TIZEN_CORE
+
_efl_loop_timer_util_delay(pd, add);
}
EOLIAN static void
_efl_loop_timer_timer_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ tcore_timer_reset(timer);
+ return;
+ }
+#endif // USE_TIZEN_CORE
+
double now, add;
if (!timer->loop_data) return;
EOLIAN static void
_efl_loop_timer_timer_loop_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ tcore_timer_reset(timer);
+ return;
+ }
+#endif // USE_TIZEN_CORE
+
double now, add;
if (!timer->loop_data) return;
EOLIAN static double
_efl_loop_timer_time_pending_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ double ret = tcore_timer_get_pending_time(timer);
+ return ret / 1000.0;
+ }
+#endif // USE_TIZEN_CORE
+
double now, ret = 0.0;
now = ecore_time_get();
EAPI void
ecore_timer_freeze(Ecore_Timer *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ tcore_timer_freeze(timer);
+ return;
+ }
+#endif // USE_TIZEN_CORE
+
ECORE_TIMER_CHECK(timer);
efl_event_freeze(timer);
}
EAPI Eina_Bool
ecore_timer_freeze_get(Ecore_Timer *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ return tcore_timer_is_running(timer);
+ }
+#endif // USE_TIZEN_CORE
+
EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
return !!efl_event_freeze_count_get(timer);
}
EAPI void
ecore_timer_thaw(Ecore_Timer *timer)
{
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready())
+ {
+ tcore_timer_thaw(timer);
+ return;
+ }
+#endif // USE_TIZEN_CORE
ECORE_TIMER_CHECK(timer);
efl_event_thaw(timer);
}
{
Eina_Inlist *first;
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready()) { return; }
+#endif // USE_TIZEN_CORE
+
efl_parent_set(efl_super(obj, EFL_LOOP_TIMER_CLASS), parent);
if ((!pd->constructed) || (!pd->finalized)) return;
EOLIAN static void
_efl_loop_timer_efl_object_destructor(Eo *obj, Efl_Loop_Timer_Data *pd)
{
+
+#ifdef USE_TIZEN_CORE
+ if (tcore_ready()) { return; }
+#endif // USE_TIZEN_CORE
+
_efl_loop_timer_util_loop_clear(pd);
efl_destructor(efl_super(obj, MY_CLASS));
}
--- /dev/null
+#include "tcore_timer.h"
+
+#include <tizen_core.h>
+
+#include <chrono>
+#include <memory>
+
+#include "log_private.h"
+#include "tcore.h"
+
+namespace {
+
+class TimerManager {
+ public:
+ class TimerTask {
+ public:
+ TimerTask(unsigned int interval, Ecore_Task_Cb cb, const void* data)
+ : interval_(interval),
+ cb_(cb),
+ data_(const_cast<void*>(data)) {}
+
+ bool Tick() {
+ SetNextTick();
+
+ if (!cb_) return false;
+
+ return static_cast<bool>(cb_(data_));
+ }
+
+ void Start() {
+ tizen_core_add_timer(tcore_get_core(), interval_, TimerCb, this,
+ &source_);
+ SetNextTick();
+ }
+
+ void* Stop() {
+ if (source_) {
+ tizen_core_remove_source(tcore_get_core(), source_);
+ source_ = nullptr;
+ }
+
+ new_interval_ = 0;
+ delay_ = 0;
+ pending_time_ = 0;
+ next_tick_ = std::chrono::milliseconds(0);
+ return data_;
+ }
+
+ void Reschedule() {
+ if (delay_) {
+ if (new_interval_ == 0) new_interval_ = interval_;
+
+ interval_ = delay_;
+ delay_ = 0;
+
+ Stop();
+ Start();
+
+ return;
+ }
+
+ if (new_interval_) {
+ interval_ = new_interval_;
+ new_interval_ = 0;
+
+ Stop();
+ Start();
+ }
+ }
+
+ void SetInterval(unsigned int interval) { interval_ = interval; }
+
+ unsigned int GetInterval() const { return interval_; }
+
+ void SetNewInterval(unsigned int interval) { new_interval_ = interval; }
+
+ unsigned int GetNewInterval() const { return new_interval_; }
+
+ void SetDelay(unsigned int delay) { delay_ = delay; }
+
+ unsigned int GetDelay() const { return delay_; }
+
+ void SetFreezePendingTime(unsigned int pending_time) {
+ pending_time_ = pending_time;
+ }
+
+ unsigned int GetFreezePendingTime() const { return pending_time_; }
+
+ bool isRunning() const { return source_ ? true : false; }
+
+ std::chrono::milliseconds GetNextTick() const { return next_tick_; }
+
+ private:
+ static bool TimerCb(void* user_data) {
+ auto* timer = static_cast<TimerTask*>(user_data);
+ unsigned int delay = timer->GetDelay();
+
+ timer->Reschedule();
+
+ if (delay != 0) return false;
+
+ return timer->Tick();
+ }
+
+ void SetNextTick() {
+ auto now = std::chrono::steady_clock::now();
+ next_tick_ = std::chrono::duration_cast<std::chrono::milliseconds>(
+ now.time_since_epoch()) +
+ std::chrono::milliseconds(interval_);
+ }
+
+ private:
+ unsigned int interval_;
+ Ecore_Task_Cb cb_;
+ void* data_;
+ tizen_core_source_h source_ = nullptr;
+ unsigned int new_interval_ = 0;
+ unsigned int delay_ = 0;
+ std::chrono::milliseconds next_tick_ = std::chrono::milliseconds(0);
+ bool frozen = false;
+ unsigned int pending_time_ = 0;
+ };
+
+ TimerManager() = default;
+
+ ~TimerManager() = default;
+
+ TimerTask* AddTimer(unsigned int interval, Ecore_Task_Cb cb,
+ const void* data) {
+ TimerManager::TimerTask* timer;
+
+ try {
+ timer = new TimerManager::TimerTask(interval, cb, data);
+ timer->Start();
+ } catch (const std::bad_alloc& e) {
+ _E("Allocation failed: %s", e.what());
+ return nullptr;
+ }
+
+ return timer;
+ }
+
+ void* DelTimer(TimerTask* timer) {
+ void* data = timer->Stop();
+ delete timer;
+
+ return data;
+ }
+
+ void SetInterval(TimerTask* timer, unsigned int interval) {
+ if (timer->GetInterval() == interval) return;
+
+ timer->SetNewInterval(interval);
+ }
+
+ unsigned int GetInterval(TimerTask* timer) {
+ unsigned int ret = timer->GetNewInterval();
+
+ if (ret) return ret;
+
+ return timer->GetInterval();
+ }
+
+ void SetDelay(TimerTask* timer, unsigned int delay) {
+ if (!timer->isRunning()) {
+ timer->SetFreezePendingTime(timer->GetFreezePendingTime() + delay);
+ return;
+ }
+ timer->SetDelay(delay);
+ }
+
+ unsigned int GetPendingTime(TimerTask* timer) {
+ if (!timer->isRunning()) return timer->GetFreezePendingTime();
+
+ auto now = std::chrono::steady_clock::now();
+ auto pendingTime = timer->GetNextTick() -
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ now.time_since_epoch());
+
+ return pendingTime.count();
+ }
+
+ void Freeze(TimerTask* timer) {
+ if (!timer->isRunning()) return;
+
+ timer->Stop();
+ timer->SetFreezePendingTime(GetPendingTime(timer));
+ }
+
+ void Thaw(TimerTask* timer) {
+ if (timer->isRunning()) return;
+
+ timer->SetNewInterval(timer->GetInterval());
+ timer->SetInterval(timer->GetFreezePendingTime());
+ timer->SetFreezePendingTime(0);
+ timer->Start();
+ }
+
+ bool IsRunning(TimerTask* timer) { return timer->isRunning(); }
+
+ void Reset(TimerTask* timer) {
+ if (timer->isRunning()) {
+ unsigned int new_interval = timer->GetNewInterval();
+ if (new_interval != 0) {
+ timer->SetNewInterval(0);
+ timer->SetInterval(new_interval);
+ }
+ timer->SetDelay(0);
+ timer->Stop();
+ timer->Start();
+ } else {
+ timer->SetFreezePendingTime(timer->GetInterval());
+ }
+ }
+};
+
+TimerManager manager;
+
+} // namespace
+
+Ecore_Timer* tcore_timer_add(unsigned int interval, Ecore_Task_Cb callback,
+ const void* user_data) {
+ if (!callback) {
+ _E("callback is null");
+ return nullptr;
+ }
+
+ return reinterpret_cast<Ecore_Timer*>(
+ manager.AddTimer(interval, callback, user_data));
+}
+
+void* tcore_timer_del(Ecore_Timer* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return nullptr;
+ }
+
+ return manager.DelTimer(reinterpret_cast<TimerManager::TimerTask*>(timer));
+}
+
+void tcore_timer_set_interval(Efl_Loop_Timer_Data* timer,
+ unsigned int interval) {
+ if (!timer) {
+ _E("timer is null");
+ return;
+ }
+
+ manager.SetInterval(reinterpret_cast<TimerManager::TimerTask*>(timer),
+ interval);
+}
+
+unsigned int tcore_timer_get_interval(Efl_Loop_Timer_Data* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return 0;
+ }
+
+ return manager.GetInterval(reinterpret_cast<TimerManager::TimerTask*>(timer));
+}
+
+void tcore_timer_set_delay(Efl_Loop_Timer_Data* timer, unsigned int delay) {
+ if (!timer) {
+ _E("timer is null");
+ return;
+ }
+
+ manager.SetDelay(reinterpret_cast<TimerManager::TimerTask*>(timer), delay);
+}
+
+void tcore_timer_reset(Efl_Loop_Timer_Data* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return;
+ }
+
+ manager.Reset(reinterpret_cast<TimerManager::TimerTask*>(timer));
+}
+
+unsigned int tcore_timer_get_pending_time(Efl_Loop_Timer_Data* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return 0;
+ }
+
+ return manager.GetPendingTime(
+ reinterpret_cast<TimerManager::TimerTask*>(timer));
+}
+
+void tcore_timer_freeze(Ecore_Timer* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return;
+ }
+
+ manager.Freeze(reinterpret_cast<TimerManager::TimerTask*>(timer));
+}
+
+Eina_Bool tcore_timer_is_running(Ecore_Timer* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return false;
+ }
+
+ return (Eina_Bool)manager.IsRunning(
+ reinterpret_cast<TimerManager::TimerTask*>(timer));
+}
+
+void tcore_timer_thaw(Ecore_Timer* timer) {
+ if (!timer) {
+ _E("timer is null");
+ return;
+ }
+
+ manager.Thaw(reinterpret_cast<TimerManager::TimerTask*>(timer));
+}