xref: /haiku/src/kits/app/MessageRunner.cpp (revision 1f4de50d39b8cbaa5c9f83477e695038c0f76fcb)
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 //! Privatized copy constructor to prevent usage.
172 BMessageRunner::BMessageRunner(const BMessageRunner &)
173 	:
174 	fToken(-1)
175 {
176 }
177 
178 
179 //! Privatized assignment operator to prevent usage.
180 BMessageRunner&
181 BMessageRunner::operator=(const BMessageRunner&)
182 {
183 	return* this;
184 }
185 
186 
187 /*!	Initializes the BMessageRunner.
188 
189 	The success of the initialization can (and should) be asked for via
190 	InitCheck().
191 
192 	\note As soon as the last message has been sent, the message runner
193 	      becomes unusable. InitCheck() will still return \c B_OK, but
194 	      SetInterval(), SetCount() and GetInfo() will fail.
195 
196 	\param target Target of the message(s).
197 	\param message The message to be sent to the target.
198 	\param interval Period of time before the first message is sent and
199 	       between messages (if more than one shall be sent) in microseconds.
200 	\param count Specifies how many times the message shall be sent.
201 	       A value less than \c 0 for an unlimited number of repetitions.
202 	\param replyTo Target replies to the delivered message(s) shall be sent to.
203 */
204 void
205 BMessageRunner::_InitData(BMessenger target, const BMessage* message,
206 	bigtime_t interval, int32 count, BMessenger replyTo)
207 {
208 	fToken = _RegisterRunner(target, message, interval, count, false, replyTo);
209 }
210 
211 
212 /*!	Registers the BMessageRunner in the registrar.
213 
214 	\param target Target of the message(s).
215 	\param message The message to be sent to the target.
216 	\param interval Period of time before the first message is sent and
217 	       between messages (if more than one shall be sent) in microseconds.
218 	\param count Specifies how many times the message shall be sent.
219 	       A value less than \c 0 for an unlimited number of repetitions.
220 	\param replyTo Target replies to the delivered message(s) shall be sent to.
221 
222 	\return The token the message runner is registered with, or the error code
223 	        while trying to register it.
224 */
225 /*static*/ int32
226 BMessageRunner::_RegisterRunner(BMessenger target, const BMessage* message,
227 	bigtime_t interval, int32 count, bool detach, BMessenger replyTo)
228 {
229 	status_t result = B_OK;
230 	if (message == NULL || count == 0 || (count < 0 && detach))
231 		result = B_BAD_VALUE;
232 
233 	// compose the request message
234 	BMessage request(B_REG_REGISTER_MESSAGE_RUNNER);
235 	if (result == B_OK)
236 		result = request.AddInt32("team", BPrivate::current_team());
237 
238 	if (result == B_OK)
239 		result = request.AddMessenger("target", target);
240 
241 	if (result == B_OK)
242 		result = request.AddMessage("message", message);
243 
244 	if (result == B_OK)
245 		result = request.AddInt64("interval", interval);
246 
247 	if (result == B_OK)
248 		result = request.AddInt32("count", count);
249 
250 	if (result == B_OK)
251 		result = request.AddMessenger("reply_target", replyTo);
252 
253 	// send the request
254 	BMessage reply;
255 	if (result == B_OK)
256 		result = BRoster::Private().SendTo(&request, &reply, false);
257 
258 	int32 token;
259 
260 	// evaluate the reply
261 	if (result == B_OK) {
262 		if (reply.what == B_REG_SUCCESS) {
263 			if (reply.FindInt32("token", &token) != B_OK)
264 				result = B_ERROR;
265 		} else {
266 			if (reply.FindInt32("error", &result) != B_OK)
267 				result = B_ERROR;
268 		}
269 	}
270 
271 	if (result == B_OK)
272 		return token;
273 
274 	return result;
275 }
276 
277 
278 /*!	Sets the message runner's interval and count parameters.
279 
280 	The parameters \a resetInterval and \a resetCount specify whether
281 	the interval or the count parameter respectively shall be reset.
282 
283 	At least one parameter must be set, otherwise the methods returns
284 	\c B_BAD_VALUE.
285 
286 	\param resetInterval \c true, if the interval shall be reset, \c false
287 	       otherwise -- then \a interval is ignored.
288 	\param interval The new interval in microseconds.
289 	\param resetCount \c true, if the count shall be reset, \c false
290 	       otherwise -- then \a count is ignored.
291 	\param count Specifies how many times the message shall be sent.
292 	       A value less than \c 0 for an unlimited number of repetitions.
293 
294 	\return A status code.
295 	\retval B_OK Everything went fine.
296 	\retval B_BAD_VALUE The message runner is not longer valid. All the
297 	        messages that had to be sent have already been sent. Or both
298 	        \a resetInterval and \a resetCount are \c false.
299 */
300 status_t
301 BMessageRunner::_SetParams(bool resetInterval, bigtime_t interval,
302 	bool resetCount, int32 count)
303 {
304 	if ((!resetInterval && !resetCount) || fToken < 0)
305 		return B_BAD_VALUE;
306 
307 	// compose the request message
308 	BMessage request(B_REG_SET_MESSAGE_RUNNER_PARAMS);
309 	status_t result = request.AddInt32("token", fToken);
310 	if (result == B_OK && resetInterval)
311 		result = request.AddInt64("interval", interval);
312 
313 	if (result == B_OK && resetCount)
314 		result = request.AddInt32("count", count);
315 
316 	// send the request
317 	BMessage reply;
318 	if (result == B_OK)
319 		result = BRoster::Private().SendTo(&request, &reply, false);
320 
321 	// evaluate the reply
322 	if (result == B_OK) {
323 		if (reply.what != B_REG_SUCCESS) {
324 			if (reply.FindInt32("error", &result) != B_OK)
325 				result = B_ERROR;
326 		}
327 	}
328 
329 	return result;
330 }
331