1 /* vi: set et sw=4 ts=8 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
3 /*
4  * This file is part of mission-control
5  *
6  * Copyright (C) 2007 Nokia Corporation.
7  *
8  * Contact: Naba Kumar  <naba.kumar@nokia.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * version 2.1 as published by the Free Software Foundation.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23  *
24  */
25 
26 /**
27  * SECTION:mcd-mission
28  * @title: McdMission
29  * @short_description: Base class for server classes
30  * @see_also:
31  * @stability: Unstable
32  * @include: mcd-mission.h
33  *
34  * It is the base class for every object in mission-control. It defines
35  * a set of virtual functions and set of corresponding action signals.
36  * all virtual functions results in emission of their corresponding action
37  * signals. The virtual functions define states of the object, such
38  * as memory conserved state, connected state, locked state, low power state,
39  * lit state, sleeping state etc. Each of the object states can also be queried
40  * independently as properties.
41  *
42  * There are also some action signals such as abort, which is used to notify
43  * other objects holding hard references to it to release them (this object
44  * should then automatically die since all held references are released). It
45  * is mandatory for all other objects that hold a hard reference to it to
46  * listen for this signal and release the reference in signal handler.
47  *
48  * Concrete derived classes should override the sate  methods to implement
49  * object specific state managements.
50  */
51 
52 #include "config.h"
53 
54 #include "mcd-mission-priv.h"
55 
56 #include <telepathy-glib/telepathy-glib.h>
57 
58 #include "mcd-enum-types.h"
59 
60 #define MCD_MISSION_PRIV(mission) (G_TYPE_INSTANCE_GET_PRIVATE ((mission), \
61 				   MCD_TYPE_MISSION, \
62 				   McdMissionPrivate))
63 
64 G_DEFINE_TYPE (McdMission, mcd_mission, G_TYPE_OBJECT);
65 
66 /* Private */
67 
68 typedef struct _McdMissionPrivate
69 {
70     McdMission *parent;
71 
72     gboolean connected;
73     gboolean is_disposed;
74 
75 } McdMissionPrivate;
76 
77 enum _McdMissionSignalType
78 {
79     CONNECTED,
80     DISCONNECTED,
81     PARENT_SET,
82     ABORT,
83     LAST_SIGNAL
84 };
85 
86 enum _McdMissionPropertyType
87 {
88     PROP_0,
89     PROP_PARENT
90 };
91 
92 static guint mcd_mission_signals[LAST_SIGNAL] = { 0 };
93 
94 static void
_mcd_mission_connect(McdMission * mission)95 _mcd_mission_connect (McdMission * mission)
96 {
97     McdMissionPrivate *priv;
98 
99     g_return_if_fail (MCD_IS_MISSION (mission));
100     priv = MCD_MISSION_PRIV (mission);
101 
102     if (!priv->connected)
103     {
104         priv->connected = TRUE;
105         g_signal_emit_by_name (mission, "connected");
106     }
107 }
108 
109 static void
_mcd_mission_disconnect(McdMission * mission)110 _mcd_mission_disconnect (McdMission * mission)
111 {
112     McdMissionPrivate *priv;
113 
114     g_return_if_fail (MCD_IS_MISSION (mission));
115     priv = MCD_MISSION_PRIV (mission);
116 
117     if (priv->connected)
118     {
119         priv->connected = FALSE;
120         g_signal_emit_by_name (mission, "disconnected");
121     }
122 }
123 
124 static void
on_parent_abort(McdMission * parent,McdMission * mission)125 on_parent_abort (McdMission *parent, McdMission *mission)
126 {
127     DEBUG ("called");
128     _mcd_mission_set_parent (mission, NULL);
129 }
130 
131 void
_mcd_mission_set_parent(McdMission * mission,McdMission * parent)132 _mcd_mission_set_parent (McdMission * mission, McdMission * parent)
133 {
134     McdMissionPrivate *priv;
135 
136     g_return_if_fail (MCD_IS_MISSION (mission));
137     g_return_if_fail ((parent == NULL) || MCD_IS_MISSION (parent));
138 
139     priv = MCD_MISSION_PRIV (mission);
140 
141     DEBUG ("child = %p, parent = %p", mission, parent);
142 
143     if (priv->parent)
144     {
145 	g_signal_handlers_disconnect_by_func (priv->parent,
146 					      on_parent_abort,
147 					      mission);
148     }
149 
150     if (parent)
151     {
152 	g_signal_connect (parent, "abort",
153 			  G_CALLBACK (on_parent_abort),
154 			  mission);
155 	g_object_ref (parent);
156     }
157 
158     tp_clear_object (&priv->parent);
159     priv->parent = parent;
160 }
161 
162 static void
_mcd_mission_abort(McdMission * mission)163 _mcd_mission_abort (McdMission * mission)
164 {
165     g_signal_emit_by_name (G_OBJECT (mission), "abort");
166 }
167 
168 static void
_mcd_mission_dispose(GObject * object)169 _mcd_mission_dispose (GObject * object)
170 {
171     McdMissionPrivate *priv;
172     g_return_if_fail (MCD_IS_MISSION (object));
173 
174     priv = MCD_MISSION_PRIV (object);
175 
176     if (priv->is_disposed)
177     {
178 	return;
179     }
180 
181     priv->is_disposed = TRUE;
182 
183     DEBUG ("mission disposed %p", object);
184     if (priv->parent)
185     {
186 	g_signal_handlers_disconnect_by_func (priv->parent,
187 					      on_parent_abort,
188 					      object);
189     }
190 
191     tp_clear_object (&priv->parent);
192 
193     G_OBJECT_CLASS (mcd_mission_parent_class)->dispose (object);
194 }
195 
196 static void
_mcd_mission_finalize(GObject * object)197 _mcd_mission_finalize (GObject * object)
198 {
199     DEBUG ("mission finalized %p", object);
200     G_OBJECT_CLASS (mcd_mission_parent_class)->finalize (object);
201 }
202 
203 static void
_mcd_set_property(GObject * object,guint prop_id,const GValue * val,GParamSpec * pspec)204 _mcd_set_property (GObject * object, guint prop_id, const GValue * val,
205 		   GParamSpec * pspec)
206 {
207     McdMission *mission = MCD_MISSION (object);
208 
209     switch (prop_id)
210     {
211     case PROP_PARENT:
212 	_mcd_mission_set_parent (mission, g_value_get_object (val));
213 	break;
214     default:
215 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216 	break;
217     }
218 }
219 
220 static void
_mcd_get_property(GObject * object,guint prop_id,GValue * val,GParamSpec * pspec)221 _mcd_get_property (GObject * object, guint prop_id, GValue * val,
222 		   GParamSpec * pspec)
223 {
224     McdMission *mission = MCD_MISSION (object);
225 
226     switch (prop_id)
227     {
228     case PROP_PARENT:
229 	g_value_set_object (val, mcd_mission_get_parent (mission));
230 	break;
231     default:
232 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
233 	break;
234     }
235 }
236 
237 static void
mcd_mission_class_init(McdMissionClass * klass)238 mcd_mission_class_init (McdMissionClass * klass)
239 {
240     GObjectClass *object_class = G_OBJECT_CLASS (klass);
241     g_type_class_add_private (object_class, sizeof (McdMissionPrivate));
242 
243     /* virtual medthods */
244     object_class->finalize = _mcd_mission_finalize;
245     object_class->dispose = _mcd_mission_dispose;
246     object_class->set_property = _mcd_set_property;
247     object_class->get_property = _mcd_get_property;
248 
249     /* virtual medthods */
250     klass->abort = _mcd_mission_abort;
251     klass->connect = _mcd_mission_connect;
252     klass->disconnect = _mcd_mission_disconnect;
253 
254     /* signals */
255     mcd_mission_signals[ABORT] =
256 	g_signal_new ("abort",
257 		      G_OBJECT_CLASS_TYPE (klass),
258 		      G_SIGNAL_RUN_FIRST,
259 		      G_STRUCT_OFFSET (McdMissionClass, abort_signal),
260 		      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
261 		      0);
262     mcd_mission_signals[CONNECTED] =
263 	g_signal_new ("connected", G_OBJECT_CLASS_TYPE (klass),
264 		      G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (McdMissionClass,
265 							   connected_signal),
266 		      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
267 		      0);
268     mcd_mission_signals[DISCONNECTED] =
269 	g_signal_new ("disconnected", G_OBJECT_CLASS_TYPE (klass),
270 		      G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (McdMissionClass,
271 							   disconnected_signal),
272 		      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
273 		      0);
274 }
275 
276 static void
mcd_mission_init(McdMission * obj)277 mcd_mission_init (McdMission * obj)
278 {
279 }
280 
281 /* Public methods */
282 
283 void
mcd_mission_connect(McdMission * mission)284 mcd_mission_connect (McdMission * mission)
285 {
286     g_return_if_fail (MCD_IS_MISSION (mission));
287     MCD_MISSION_GET_CLASS (mission)->connect (mission);
288 }
289 
290 void
mcd_mission_disconnect(McdMission * mission)291 mcd_mission_disconnect (McdMission * mission)
292 {
293     g_return_if_fail (MCD_IS_MISSION (mission));
294     MCD_MISSION_GET_CLASS (mission)->disconnect (mission);
295 }
296 
297 void
mcd_mission_abort(McdMission * mission)298 mcd_mission_abort (McdMission * mission)
299 {
300     g_return_if_fail (MCD_IS_MISSION (mission));
301     MCD_MISSION_GET_CLASS (mission)->abort (mission);
302 }
303 
304 gboolean
mcd_mission_is_connected(McdMission * mission)305 mcd_mission_is_connected (McdMission * mission)
306 {
307     McdMissionPrivate *priv;
308 
309     g_return_val_if_fail (MCD_IS_MISSION (mission), FALSE);
310     priv = MCD_MISSION_PRIV (mission);
311 
312     return priv->connected;
313 }
314 
315 McdMission *
mcd_mission_get_parent(McdMission * mission)316 mcd_mission_get_parent (McdMission * mission)
317 {
318     McdMissionPrivate *priv;
319 
320     g_return_val_if_fail (MCD_IS_MISSION (mission), NULL);
321     priv = MCD_MISSION_PRIV (mission);
322 
323     return priv->parent;
324 }
325