1 /*
2 * Copyright 2001-2010 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Ingo Weinhold, ingo_weinhold@gmx.de
7 */
8
9
10 #include <MessageRunner.h>
11
12 #include <Application.h>
13 #include <AppMisc.h>
14 #include <RegistrarDefs.h>
15 #include <Roster.h>
16 #include <RosterPrivate.h>
17
18
19 using namespace BPrivate;
20
21
BMessageRunner(BMessenger target,const BMessage * message,bigtime_t interval,int32 count)22 BMessageRunner::BMessageRunner(BMessenger target, const BMessage* message,
23 bigtime_t interval, int32 count)
24 :
25 fToken(-1)
26 {
27 _InitData(target, message, interval, count, be_app_messenger);
28 }
29
30
BMessageRunner(BMessenger target,const BMessage & message,bigtime_t interval,int32 count)31 BMessageRunner::BMessageRunner(BMessenger target, const BMessage& message,
32 bigtime_t interval, int32 count)
33 :
34 fToken(-1)
35 {
36 _InitData(target, &message, interval, count, be_app_messenger);
37 }
38
39
BMessageRunner(BMessenger target,const BMessage * message,bigtime_t interval,int32 count,BMessenger replyTo)40 BMessageRunner::BMessageRunner(BMessenger target, const BMessage* message,
41 bigtime_t interval, int32 count, BMessenger replyTo)
42 :
43 fToken(-1)
44 {
45 _InitData(target, message, interval, count, replyTo);
46 }
47
48
BMessageRunner(BMessenger target,const BMessage & message,bigtime_t interval,int32 count,BMessenger replyTo)49 BMessageRunner::BMessageRunner(BMessenger target, const BMessage& message,
50 bigtime_t interval, int32 count, BMessenger replyTo)
51 :
52 fToken(-1)
53 {
54 _InitData(target, &message, interval, count, replyTo);
55 }
56
57
~BMessageRunner()58 BMessageRunner::~BMessageRunner()
59 {
60 if (fToken < B_OK)
61 return;
62
63 // compose the request message
64 BMessage request(B_REG_UNREGISTER_MESSAGE_RUNNER);
65 status_t result = request.AddInt32("token", fToken);
66
67 // send the request
68 BMessage reply;
69 if (result == B_OK)
70 result = BRoster::Private().SendTo(&request, &reply, false);
71
72 // ignore the reply, we can't do anything anyway
73 }
74
75
76 status_t
InitCheck() const77 BMessageRunner::InitCheck() const
78 {
79 return fToken >= 0 ? B_OK : fToken;
80 }
81
82
83 status_t
SetInterval(bigtime_t interval)84 BMessageRunner::SetInterval(bigtime_t interval)
85 {
86 return _SetParams(true, interval, false, 0);
87 }
88
89
90 status_t
SetCount(int32 count)91 BMessageRunner::SetCount(int32 count)
92 {
93 return _SetParams(false, 0, true, count);
94 }
95
96
97 status_t
GetInfo(bigtime_t * interval,int32 * count) const98 BMessageRunner::GetInfo(bigtime_t* interval, int32* count) const
99 {
100 status_t result = fToken >= 0 ? B_OK : B_BAD_VALUE;
101
102 // compose the request message
103 BMessage request(B_REG_GET_MESSAGE_RUNNER_INFO);
104 if (result == B_OK)
105 result = request.AddInt32("token", fToken);
106
107 // send the request
108 BMessage reply;
109 if (result == B_OK)
110 result = BRoster::Private().SendTo(&request, &reply, false);
111
112 // evaluate the reply
113 if (result == B_OK) {
114 if (reply.what == B_REG_SUCCESS) {
115 // count
116 int32 _count;
117 if (reply.FindInt32("count", &_count) == B_OK) {
118 if (count != 0)
119 *count = _count;
120 } else
121 result = B_ERROR;
122
123 // interval
124 bigtime_t _interval;
125 if (reply.FindInt64("interval", &_interval) == B_OK) {
126 if (interval != 0)
127 *interval = _interval;
128 } else
129 result = B_ERROR;
130 } else {
131 if (reply.FindInt32("error", &result) != B_OK)
132 result = B_ERROR;
133 }
134 }
135
136 return result;
137 }
138
139
140 /*static*/ status_t
StartSending(BMessenger target,const BMessage * message,bigtime_t interval,int32 count)141 BMessageRunner::StartSending(BMessenger target, const BMessage* message,
142 bigtime_t interval, int32 count)
143 {
144 int32 token = _RegisterRunner(target, message, interval, count, true,
145 be_app_messenger);
146
147 return token >= B_OK ? B_OK : token;
148 }
149
150
151 /*static*/ status_t
StartSending(BMessenger target,const BMessage * message,bigtime_t interval,int32 count,BMessenger replyTo)152 BMessageRunner::StartSending(BMessenger target, const BMessage* message,
153 bigtime_t interval, int32 count, BMessenger replyTo)
154 {
155 int32 token = _RegisterRunner(target, message, interval, count, true,
156 replyTo);
157
158 return token >= B_OK ? B_OK : token;
159 }
160
161
162 // FBC
_ReservedMessageRunner1()163 void BMessageRunner::_ReservedMessageRunner1() {}
_ReservedMessageRunner2()164 void BMessageRunner::_ReservedMessageRunner2() {}
_ReservedMessageRunner3()165 void BMessageRunner::_ReservedMessageRunner3() {}
_ReservedMessageRunner4()166 void BMessageRunner::_ReservedMessageRunner4() {}
_ReservedMessageRunner5()167 void BMessageRunner::_ReservedMessageRunner5() {}
_ReservedMessageRunner6()168 void BMessageRunner::_ReservedMessageRunner6() {}
169
170
171 #ifdef __HAIKU_BEOS_COMPATIBLE
172 //! Privatized copy constructor to prevent usage.
BMessageRunner(const BMessageRunner &)173 BMessageRunner::BMessageRunner(const BMessageRunner &)
174 :
175 fToken(-1)
176 {
177 }
178
179
180 //! Privatized assignment operator to prevent usage.
181 BMessageRunner&
operator =(const BMessageRunner &)182 BMessageRunner::operator=(const BMessageRunner&)
183 {
184 return* this;
185 }
186 #endif
187
188
189 /*! Initializes the BMessageRunner.
190
191 The success of the initialization can (and should) be asked for via
192 InitCheck().
193
194 \note As soon as the last message has been sent, the message runner
195 becomes unusable. InitCheck() will still return \c B_OK, but
196 SetInterval(), SetCount() and GetInfo() will fail.
197
198 \param target Target of the message(s).
199 \param message The message to be sent to the target.
200 \param interval Period of time before the first message is sent and
201 between messages (if more than one shall be sent) in microseconds.
202 \param count Specifies how many times the message shall be sent.
203 A value less than \c 0 for an unlimited number of repetitions.
204 \param replyTo Target replies to the delivered message(s) shall be sent to.
205 */
206 void
_InitData(BMessenger target,const BMessage * message,bigtime_t interval,int32 count,BMessenger replyTo)207 BMessageRunner::_InitData(BMessenger target, const BMessage* message,
208 bigtime_t interval, int32 count, BMessenger replyTo)
209 {
210 fToken = _RegisterRunner(target, message, interval, count, false, replyTo);
211 }
212
213
214 /*! Registers the BMessageRunner in the registrar.
215
216 \param target Target of the message(s).
217 \param message The message to be sent to the target.
218 \param interval Period of time before the first message is sent and
219 between messages (if more than one shall be sent) in microseconds.
220 \param count Specifies how many times the message shall be sent.
221 A value less than \c 0 for an unlimited number of repetitions.
222 \param replyTo Target replies to the delivered message(s) shall be sent to.
223
224 \return The token the message runner is registered with, or the error code
225 while trying to register it.
226 */
227 /*static*/ int32
_RegisterRunner(BMessenger target,const BMessage * message,bigtime_t interval,int32 count,bool detach,BMessenger replyTo)228 BMessageRunner::_RegisterRunner(BMessenger target, const BMessage* message,
229 bigtime_t interval, int32 count, bool detach, BMessenger replyTo)
230 {
231 status_t result = B_OK;
232 if (message == NULL || count == 0 || (count < 0 && detach))
233 result = B_BAD_VALUE;
234
235 // compose the request message
236 BMessage request(B_REG_REGISTER_MESSAGE_RUNNER);
237 if (result == B_OK)
238 result = request.AddInt32("team", BPrivate::current_team());
239
240 if (result == B_OK)
241 result = request.AddMessenger("target", target);
242
243 if (result == B_OK)
244 result = request.AddMessage("message", message);
245
246 if (result == B_OK)
247 result = request.AddInt64("interval", interval);
248
249 if (result == B_OK)
250 result = request.AddInt32("count", count);
251
252 if (result == B_OK)
253 result = request.AddMessenger("reply_target", replyTo);
254
255 // send the request
256 BMessage reply;
257 if (result == B_OK)
258 result = BRoster::Private().SendTo(&request, &reply, false);
259
260 int32 token;
261
262 // evaluate the reply
263 if (result == B_OK) {
264 if (reply.what == B_REG_SUCCESS) {
265 if (reply.FindInt32("token", &token) != B_OK)
266 result = B_ERROR;
267 } else {
268 if (reply.FindInt32("error", &result) != B_OK)
269 result = B_ERROR;
270 }
271 }
272
273 if (result == B_OK)
274 return token;
275
276 return result;
277 }
278
279
280 /*! Sets the message runner's interval and count parameters.
281
282 The parameters \a resetInterval and \a resetCount specify whether
283 the interval or the count parameter respectively shall be reset.
284
285 At least one parameter must be set, otherwise the methods returns
286 \c B_BAD_VALUE.
287
288 \param resetInterval \c true, if the interval shall be reset, \c false
289 otherwise -- then \a interval is ignored.
290 \param interval The new interval in microseconds.
291 \param resetCount \c true, if the count shall be reset, \c false
292 otherwise -- then \a count is ignored.
293 \param count Specifies how many times the message shall be sent.
294 A value less than \c 0 for an unlimited number of repetitions.
295
296 \return A status code.
297 \retval B_OK Everything went fine.
298 \retval B_BAD_VALUE The message runner is not longer valid. All the
299 messages that had to be sent have already been sent. Or both
300 \a resetInterval and \a resetCount are \c false.
301 */
302 status_t
_SetParams(bool resetInterval,bigtime_t interval,bool resetCount,int32 count)303 BMessageRunner::_SetParams(bool resetInterval, bigtime_t interval,
304 bool resetCount, int32 count)
305 {
306 if ((!resetInterval && !resetCount) || fToken < 0)
307 return B_BAD_VALUE;
308
309 // compose the request message
310 BMessage request(B_REG_SET_MESSAGE_RUNNER_PARAMS);
311 status_t result = request.AddInt32("token", fToken);
312 if (result == B_OK && resetInterval)
313 result = request.AddInt64("interval", interval);
314
315 if (result == B_OK && resetCount)
316 result = request.AddInt32("count", count);
317
318 // send the request
319 BMessage reply;
320 if (result == B_OK)
321 result = BRoster::Private().SendTo(&request, &reply, false);
322
323 // evaluate the reply
324 if (result == B_OK) {
325 if (reply.what != B_REG_SUCCESS) {
326 if (reply.FindInt32("error", &result) != B_OK)
327 result = B_ERROR;
328 }
329 }
330
331 return result;
332 }
333