summaryrefslogtreecommitdiff
path: root/src/services/clock-service.c
blob: c95701181f052348f484ed422675e660f827a2f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "services/clock-service.h"

//
// FoobarClockService:
//
// Service providing an auto-updating timestamp value which can be used to display the current time.
//

struct _FoobarClockService
{
	GObject    parent_instance;
	GDateTime* time;
	guint      source_id;
};

enum
{
	PROP_TIME = 1,
	N_PROPS,
};

static GParamSpec* props[N_PROPS] = { 0 };

static void     foobar_clock_service_class_init  ( FoobarClockServiceClass* klass );
static void     foobar_clock_service_init        ( FoobarClockService*      self );
static void     foobar_clock_service_get_property( GObject*                 object,
                                                   guint                    prop_id,
                                                   GValue*                  value,
                                                   GParamSpec*              pspec );
static void     foobar_clock_service_finalize    ( GObject*                 object );
static gboolean foobar_clock_service_handle_tick ( gpointer                 userdata );

G_DEFINE_FINAL_TYPE( FoobarClockService, foobar_clock_service, G_TYPE_OBJECT )

// ---------------------------------------------------------------------------------------------------------------------
// Service Implementation
// ---------------------------------------------------------------------------------------------------------------------

//
// Static initialization for the clock service.
//
void foobar_clock_service_class_init( FoobarClockServiceClass* klass )
{
	GObjectClass* object_klass = G_OBJECT_CLASS( klass );
	object_klass->get_property = foobar_clock_service_get_property;
	object_klass->finalize = foobar_clock_service_finalize;

	props[PROP_TIME] = g_param_spec_boxed(
		"time",
		"Time",
		"The current time, regularly updated.",
		G_TYPE_DATE_TIME,
		G_PARAM_READABLE );
	g_object_class_install_properties( object_klass, N_PROPS, props );
}

//
// Instance initialization for the clock service.
//
void foobar_clock_service_init( FoobarClockService* self )
{
	self->time = g_date_time_new_now_local( );
	self->source_id = g_timeout_add_seconds( 1, foobar_clock_service_handle_tick, self );
}

//
// Property getter implementation, mapping a property id to a method.
//
void foobar_clock_service_get_property(
	GObject*    object,
	guint       prop_id,
	GValue*     value,
	GParamSpec* pspec )
{
	FoobarClockService* self = (FoobarClockService*)object;

	switch ( prop_id )
	{
		case PROP_TIME:
			g_value_set_boxed( value, foobar_clock_service_get_time( self ) );
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
			break;
	}
}

//
// Instance cleanup for the clock service.
//
void foobar_clock_service_finalize( GObject* object )
{
	FoobarClockService* self = (FoobarClockService*)object;

	g_clear_pointer( &self->time, g_date_time_unref );
	g_clear_handle_id( &self->source_id, g_source_remove );

	G_OBJECT_CLASS( foobar_clock_service_parent_class )->finalize( object );
}

// ---------------------------------------------------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------------------------------------------------

//
// Create a new clock service instance.
//
FoobarClockService* foobar_clock_service_new( void )
{
	return g_object_new( FOOBAR_TYPE_CLOCK_SERVICE, NULL );
}

//
// Get the current snapshot of the timestamp.
//
// This may be a bit older than the value returned by g_date_time_new_now_local.
//
GDateTime* foobar_clock_service_get_time( FoobarClockService* self )
{
	g_return_val_if_fail( FOOBAR_IS_CLOCK_SERVICE( self ), NULL );

	return self->time;
}

// ---------------------------------------------------------------------------------------------------------------------
// Signal Handlers
// ---------------------------------------------------------------------------------------------------------------------

//
// Called every time the update delay has elapsed to update the current timestamp value.
//
gboolean foobar_clock_service_handle_tick( gpointer userdata )
{
	FoobarClockService* self = (FoobarClockService*)userdata;

	g_clear_pointer( &self->time, g_date_time_unref );
	self->time = g_date_time_new_now_local( );
	g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_TIME] );

	return G_SOURCE_CONTINUE;
}