xref: /haiku/src/kits/app/MessageRunner.cpp (revision 495060760727dd782c9f8a90db71e5d727f19748)
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 
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 
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 
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 
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 
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
77 BMessageRunner::InitCheck() const
78 {
79 	return fToken >= 0 ? B_OK : fToken;
80 }
81 
82 
83 status_t
84 BMessageRunner::SetInterval(bigtime_t interval)
85 {
86 	return _SetParams(true, interval, false, 0);
87 }
88 
89 
90 status_t
91 BMessageRunner::SetCount(int32 count)
92 {
93 	return _SetParams(false, 0, true, count);
94 }
95 
96 
97 status_t
98 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
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
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
163 void BMessageRunner::_ReservedMessageRunner1() {}
164 void BMessageRunner::_ReservedMessageRunner2() {}
165 void BMessageRunner::_ReservedMessageRunner3() {}
166 void BMessageRunner::_ReservedMessageRunner4() {}
167 void BMessageRunner::_ReservedMessageRunner5() {}
168 void BMessageRunner::_ReservedMessageRunner6() {}
169 
170 
171 #ifdef _BEOS_R5_COMPATIBLE_
172 //! Privatized copy constructor to prevent usage.
173 BMessageRunner::BMessageRunner(const BMessageRunner &)
174 	:
175 	fToken(-1)
176 {
177 }
178 
179 
180 //! Privatized assignment operator to prevent usage.
181 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
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
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
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