xref: /haiku/src/kits/app/MessageRunner.cpp (revision d67f94ca9dc693a2734456fa13111d2036bc7297)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		MessageRunner.cpp
23 //	Author:			Ingo Weinhold (bonefish@users.sf.net)
24 //	Description:	A BMessageRunner periodically sends a message to a
25 //                  specified target.
26 //------------------------------------------------------------------------------
27 #include <Application.h>
28 #include <AppMisc.h>
29 #include <MessageRunner.h>
30 #include <RegistrarDefs.h>
31 #include <Roster.h>
32 #include <RosterPrivate.h>
33 
34 using namespace BPrivate;
35 
36 // constructor
37 /*!	\brief Creates and initializes a new BMessageRunner.
38 
39 	The target for replies to the delivered message(s) is \c be_app_messenger.
40 
41 	The success of the initialization can (and should) be asked for via
42 	InitCheck().
43 
44 	\note As soon as the last message has been sent, the message runner
45 		  becomes unusable. InitCheck() will still return \c B_OK, but
46 		  SetInterval(), SetCount() and GetInfo() will fail.
47 
48 	\param target Target of the message(s).
49 	\param message The message to be sent to the target.
50 	\param interval Period of time before the first message is sent and
51 		   between messages (if more than one shall be sent) in microseconds.
52 	\param count Specifies how many times the message shall be sent.
53 		   A value less than \c 0 for an unlimited number of repetitions.
54 */
55 BMessageRunner::BMessageRunner(BMessenger target, const BMessage *message,
56 							   bigtime_t interval, int32 count)
57 	: fToken(-1)
58 {
59 	InitData(target, message, interval, count, be_app_messenger);
60 }
61 
62 // constructor
63 /*!	\brief Creates and initializes a new BMessageRunner.
64 
65 	This constructor version additionally allows to specify the target for
66 	replies to the delivered message(s).
67 
68 	The success of the initialization can (and should) be asked for via
69 	InitCheck().
70 
71 	\note As soon as the last message has been sent, the message runner
72 		  becomes unusable. InitCheck() will still return \c B_OK, but
73 		  SetInterval(), SetCount() and GetInfo() will fail.
74 
75 	\param target Target of the message(s).
76 	\param message The message to be sent to the target.
77 	\param interval Period of time before the first message is sent and
78 		   between messages (if more than one shall be sent) in microseconds.
79 	\param count Specifies how many times the message shall be sent.
80 		   A value less than \c 0 for an unlimited number of repetitions.
81 	\param replyTo Target replies to the delivered message(s) shall be sent to.
82 */
83 BMessageRunner::BMessageRunner(BMessenger target, const BMessage *message,
84 							   bigtime_t interval, int32 count,
85 							   BMessenger replyTo)
86 	: fToken(-1)
87 {
88 	InitData(target, message, interval, count, replyTo);
89 }
90 
91 // destructor
92 /*!	\brief Frees all resources associated with the object.
93 */
94 BMessageRunner::~BMessageRunner()
95 {
96 	status_t error = B_OK;
97 	// compose the request message
98 	BMessage request(B_REG_UNREGISTER_MESSAGE_RUNNER);
99 	if (error == B_OK)
100 		error = request.AddInt32("token", fToken);
101 	// send the request
102 	BMessage reply;
103 	if (error == B_OK)
104 		error = BRoster::Private().SendTo(&request, &reply, false);
105 	// ignore the reply, we can't do anything anyway
106 }
107 
108 // InitCheck
109 /*!	\brief Returns the status of the initialization.
110 
111 	\note As soon as the last message has been sent, the message runner
112 		  becomes unusable. InitCheck() will still return \c B_OK, but
113 		  SetInterval(), SetCount() and GetInfo() will fail.
114 
115 	\return \c B_OK, if the object is properly initialized, an error code
116 			otherwise.
117 */
118 status_t
119 BMessageRunner::InitCheck() const
120 {
121 	return (fToken >= 0 ? B_OK : fToken);
122 }
123 
124 // SetInterval
125 /*!	\brief Sets the interval of time between messages.
126 	\param interval The new interval in microseconds.
127 	\return
128 	- \c B_OK: Everything went fine.
129 	- \c B_NO_INIT: The message runner is not properly initialized.
130 	- \c B_BAD_VALUE: \a interval is \c 0 or negative, or the message runner
131 	  has already sent all messages to be sent and has become unusable.
132 */
133 status_t
134 BMessageRunner::SetInterval(bigtime_t interval)
135 {
136 	return SetParams(true, interval, false, 0);
137 }
138 
139 // SetCount
140 /*!	\brief Sets the number of times message shall be sent.
141 	\param count Specifies how many times the message shall be sent.
142 		   A value less than \c 0 for an unlimited number of repetitions.
143 	- \c B_BAD_VALUE: The message runner has already sent all messages to be
144 	  sent and has become unusable.
145 	\return
146 	- \c B_OK: Everything went fine.
147 	- \c B_NO_INIT: The message runner is not properly initialized.
148 */
149 status_t
150 BMessageRunner::SetCount(int32 count)
151 {
152 	return SetParams(false, 0, true, count);
153 }
154 
155 // GetInfo
156 /*!	\brief Returns the time interval between two messages and the number of
157 		   times the message has still to be sent.
158 
159 	Both parameters (\a interval and \a count) may be \c NULL.
160 
161 	\param interval Pointer to a pre-allocated bigtime_t variable to be set
162 		   to the time interval. May be \c NULL.
163 	\param count Pointer to a pre-allocated int32 variable to be set
164 		   to the number of times the message has still to be sent.
165 		   May be \c NULL.
166 	\return
167 	- \c B_OK: Everything went fine.
168 	- \c B_BAD_VALUE: The message runner is not longer valid. All the
169 	  messages that had to be sent have already been sent.
170 */
171 status_t
172 BMessageRunner::GetInfo(bigtime_t *interval, int32 *count) const
173 {
174 	status_t error =  (fToken >= 0 ? B_OK : B_BAD_VALUE);
175 	// compose the request message
176 	BMessage request(B_REG_GET_MESSAGE_RUNNER_INFO);
177 	if (error == B_OK)
178 		error = request.AddInt32("token", fToken);
179 	// send the request
180 	BMessage reply;
181 	if (error == B_OK)
182 		error = BRoster::Private().SendTo(&request, &reply, false);
183 	// evaluate the reply
184 	if (error == B_OK) {
185 		if (reply.what == B_REG_SUCCESS) {
186 			// count
187 			int32 _count;
188 			if (reply.FindInt32("count", &_count) == B_OK) {
189 				if (count)
190 					*count = _count;
191 			} else
192 				error = B_ERROR;
193 			// interval
194 			bigtime_t _interval;
195 			if (reply.FindInt64("interval", &_interval) == B_OK) {
196 				if (interval)
197 					*interval = _interval;
198 			} else
199 				error = B_ERROR;
200 		} else
201 			reply.FindInt32("error", &error);
202 	}
203 	return error;
204 }
205 
206 // FBC
207 void BMessageRunner::_ReservedMessageRunner1() {}
208 void BMessageRunner::_ReservedMessageRunner2() {}
209 void BMessageRunner::_ReservedMessageRunner3() {}
210 void BMessageRunner::_ReservedMessageRunner4() {}
211 void BMessageRunner::_ReservedMessageRunner5() {}
212 void BMessageRunner::_ReservedMessageRunner6() {}
213 
214 // copy constructor
215 /*!	\brief Privatized copy constructor to prevent usage.
216 */
217 BMessageRunner::BMessageRunner(const BMessageRunner &)
218 	: fToken(-1)
219 {
220 }
221 
222 // =
223 /*!	\brief Privatized assignment operator to prevent usage.
224 */
225 BMessageRunner &
226 BMessageRunner::operator=(const BMessageRunner &)
227 {
228 	return *this;
229 }
230 
231 // InitData
232 /*!	\brief Initializes the BMessageRunner.
233 
234 	The success of the initialization can (and should) be asked for via
235 	InitCheck().
236 
237 	\note As soon as the last message has been sent, the message runner
238 		  becomes unusable. InitCheck() will still return \c B_OK, but
239 		  SetInterval(), SetCount() and GetInfo() will fail.
240 
241 	\param target Target of the message(s).
242 	\param message The message to be sent to the target.
243 	\param interval Period of time before the first message is sent and
244 		   between messages (if more than one shall be sent) in microseconds.
245 	\param count Specifies how many times the message shall be sent.
246 		   A value less than \c 0 for an unlimited number of repetitions.
247 	\param replyTo Target replies to the delivered message(s) shall be sent to.
248 */
249 void
250 BMessageRunner::InitData(BMessenger target, const BMessage *message,
251 						 bigtime_t interval, int32 count, BMessenger replyTo)
252 {
253 	status_t error = (message ? B_OK : B_BAD_VALUE);
254 	if (error == B_OK && count == 0)
255 		error = B_ERROR;
256 	// compose the request message
257 	BMessage request(B_REG_REGISTER_MESSAGE_RUNNER);
258 	if (error == B_OK)
259 		error = request.AddInt32("team", BPrivate::current_team());
260 	if (error == B_OK)
261 		error = request.AddMessenger("target", target);
262 	if (error == B_OK)
263 		error = request.AddMessage("message", message);
264 	if (error == B_OK)
265 		error = request.AddInt64("interval", interval);
266 	if (error == B_OK)
267 		error = request.AddInt32("count", count);
268 	if (error == B_OK)
269 		error = request.AddMessenger("reply_target", replyTo);
270 	// send the request
271 	BMessage reply;
272 	if (error == B_OK)
273 		error = BRoster::Private().SendTo(&request, &reply, false);
274 	// evaluate the reply
275 	if (error == B_OK) {
276 		if (reply.what == B_REG_SUCCESS) {
277 			if (reply.FindInt32("token", &fToken) != B_OK)
278 				error = B_ERROR;
279 		} else
280 			reply.FindInt32("error", &error);
281 	}
282 	if (error != B_OK)
283 		fToken = error;
284 }
285 
286 // SetParams
287 /*!	\brief Sets the message runner's interval and count parameters.
288 
289 	The parameters \a resetInterval and \a resetCount specify whether
290 	the interval or the count parameter respectively shall be reset.
291 
292 	At least one parameter must be set, otherwise the methods returns
293 	\c B_BAD_VALUE.
294 
295 	\param resetInterval \c true, if the interval shall be reset, \c false
296 		   otherwise -- then \a interval is ignored.
297 	\param interval The new interval in microseconds.
298 	\param resetCount \c true, if the count shall be reset, \c false
299 		   otherwise -- then \a count is ignored.
300 	\param count Specifies how many times the message shall be sent.
301 		   A value less than \c 0 for an unlimited number of repetitions.
302 	\return
303 	- \c B_OK: Everything went fine.
304 	- \c B_BAD_VALUE: The message runner is not longer valid. All the
305 	  messages that had to be sent have already been sent. Or both
306 	  \a resetInterval and \a resetCount are \c false.
307 */
308 status_t
309 BMessageRunner::SetParams(bool resetInterval, bigtime_t interval,
310 						  bool resetCount, int32 count)
311 {
312 	status_t error = ((resetInterval || resetCount) && fToken >= 0
313 					  ? B_OK : B_BAD_VALUE);
314 	// compose the request message
315 	BMessage request(B_REG_SET_MESSAGE_RUNNER_PARAMS);
316 	if (error == B_OK)
317 		error = request.AddInt32("token", fToken);
318 	if (error == B_OK && resetInterval)
319 		error = request.AddInt64("interval", interval);
320 	if (error == B_OK && resetCount)
321 		error = request.AddInt32("count", count);
322 	// send the request
323 	BMessage reply;
324 	if (error == B_OK)
325 		error = BRoster::Private().SendTo(&request, &reply, false);
326 	// evaluate the reply
327 	if (error == B_OK) {
328 		if (reply.what != B_REG_SUCCESS)
329 			reply.FindInt32("error", &error);
330 	}
331 	return error;
332 }
333 
334