xref: /haiku/src/kits/app/MessageRunner.cpp (revision 51978af14a173e7fae0563b562be5603bc652aeb)
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 // constructor
35 /*!	\brief Creates and initializes a new BMessageRunner.
36 
37 	The target for replies to the delivered message(s) is \c be_app_messenger.
38 
39 	The success of the initialization can (and should) be asked for via
40 	InitCheck().
41 
42 	\note As soon as the last message has been sent, the message runner
43 		  becomes unusable. InitCheck() will still return \c B_OK, but
44 		  SetInterval(), SetCount() and GetInfo() will fail.
45 
46 	\param target Target of the message(s).
47 	\param message The message to be sent to the target.
48 	\param interval Period of time before the first message is sent and
49 		   between messages (if more than one shall be sent) in microseconds.
50 	\param count Specifies how many times the message shall be sent.
51 		   A value less than \c 0 for an unlimited number of repetitions.
52 */
53 BMessageRunner::BMessageRunner(BMessenger target, const BMessage *message,
54 							   bigtime_t interval, int32 count)
55 	: fToken(-1)
56 {
57 	InitData(target, message, interval, count, be_app_messenger);
58 }
59 
60 // constructor
61 /*!	\brief Creates and initializes a new BMessageRunner.
62 
63 	This constructor version additionally allows to specify the target for
64 	replies to the delivered message(s).
65 
66 	The success of the initialization can (and should) be asked for via
67 	InitCheck().
68 
69 	\note As soon as the last message has been sent, the message runner
70 		  becomes unusable. InitCheck() will still return \c B_OK, but
71 		  SetInterval(), SetCount() and GetInfo() will fail.
72 
73 	\param target Target of the message(s).
74 	\param message The message to be sent to the target.
75 	\param interval Period of time before the first message is sent and
76 		   between messages (if more than one shall be sent) in microseconds.
77 	\param count Specifies how many times the message shall be sent.
78 		   A value less than \c 0 for an unlimited number of repetitions.
79 	\param replyTo Target replies to the delivered message(s) shall be sent to.
80 */
81 BMessageRunner::BMessageRunner(BMessenger target, const BMessage *message,
82 							   bigtime_t interval, int32 count,
83 							   BMessenger replyTo)
84 	: fToken(-1)
85 {
86 	InitData(target, message, interval, count, replyTo);
87 }
88 
89 // destructor
90 /*!	\brief Frees all resources associated with the object.
91 */
92 BMessageRunner::~BMessageRunner()
93 {
94 	status_t error = B_OK;
95 	// compose the request message
96 	BMessage request(B_REG_UNREGISTER_MESSAGE_RUNNER);
97 	if (error == B_OK)
98 		error = request.AddInt32("token", fToken);
99 	// send the request
100 	BMessage reply;
101 	if (error == B_OK)
102 		error = BRoster::Private().SendTo(&request, &reply, false);
103 	// ignore the reply, we can't do anything anyway
104 }
105 
106 // InitCheck
107 /*!	\brief Returns the status of the initialization.
108 
109 	\note As soon as the last message has been sent, the message runner
110 		  becomes unusable. InitCheck() will still return \c B_OK, but
111 		  SetInterval(), SetCount() and GetInfo() will fail.
112 
113 	\return \c B_OK, if the object is properly initialized, an error code
114 			otherwise.
115 */
116 status_t
117 BMessageRunner::InitCheck() const
118 {
119 	return (fToken >= 0 ? B_OK : fToken);
120 }
121 
122 // SetInterval
123 /*!	\brief Sets the interval of time between messages.
124 	\param interval The new interval in microseconds.
125 	\return
126 	- \c B_OK: Everything went fine.
127 	- \c B_NO_INIT: The message runner is not properly initialized.
128 	- \c B_BAD_VALUE: \a interval is \c 0 or negative, or the message runner
129 	  has already sent all messages to be sent and has become unusable.
130 */
131 status_t
132 BMessageRunner::SetInterval(bigtime_t interval)
133 {
134 	return SetParams(true, interval, false, 0);
135 }
136 
137 // SetCount
138 /*!	\brief Sets the number of times message shall be sent.
139 	\param count Specifies how many times the message shall be sent.
140 		   A value less than \c 0 for an unlimited number of repetitions.
141 	- \c B_BAD_VALUE: The message runner has already sent all messages to be
142 	  sent and has become unusable.
143 	\return
144 	- \c B_OK: Everything went fine.
145 	- \c B_NO_INIT: The message runner is not properly initialized.
146 */
147 status_t
148 BMessageRunner::SetCount(int32 count)
149 {
150 	return SetParams(false, 0, true, count);
151 }
152 
153 // GetInfo
154 /*!	\brief Returns the time interval between two messages and the number of
155 		   times the message has still to be sent.
156 
157 	Both parameters (\a interval and \a count) may be \c NULL.
158 
159 	\param interval Pointer to a pre-allocated bigtime_t variable to be set
160 		   to the time interval. May be \c NULL.
161 	\param count Pointer to a pre-allocated int32 variable to be set
162 		   to the number of times the message has still to be sent.
163 		   May be \c NULL.
164 	\return
165 	- \c B_OK: Everything went fine.
166 	- \c B_BAD_VALUE: The message runner is not longer valid. All the
167 	  messages that had to be sent have already been sent.
168 */
169 status_t
170 BMessageRunner::GetInfo(bigtime_t *interval, int32 *count) const
171 {
172 	status_t error =  (fToken >= 0 ? B_OK : B_BAD_VALUE);
173 	// compose the request message
174 	BMessage request(B_REG_GET_MESSAGE_RUNNER_INFO);
175 	if (error == B_OK)
176 		error = request.AddInt32("token", fToken);
177 	// send the request
178 	BMessage reply;
179 	if (error == B_OK)
180 		error = BRoster::Private().SendTo(&request, &reply, false);
181 	// evaluate the reply
182 	if (error == B_OK) {
183 		if (reply.what == B_REG_SUCCESS) {
184 			// count
185 			int32 _count;
186 			if (reply.FindInt32("count", &_count) == B_OK) {
187 				if (count)
188 					*count = _count;
189 			} else
190 				error = B_ERROR;
191 			// interval
192 			bigtime_t _interval;
193 			if (reply.FindInt64("interval", &_interval) == B_OK) {
194 				if (interval)
195 					*interval = _interval;
196 			} else
197 				error = B_ERROR;
198 		} else
199 			reply.FindInt32("error", &error);
200 	}
201 	return error;
202 }
203 
204 // FBC
205 void BMessageRunner::_ReservedMessageRunner1() {}
206 void BMessageRunner::_ReservedMessageRunner2() {}
207 void BMessageRunner::_ReservedMessageRunner3() {}
208 void BMessageRunner::_ReservedMessageRunner4() {}
209 void BMessageRunner::_ReservedMessageRunner5() {}
210 void BMessageRunner::_ReservedMessageRunner6() {}
211 
212 // copy constructor
213 /*!	\brief Privatized copy constructor to prevent usage.
214 */
215 BMessageRunner::BMessageRunner(const BMessageRunner &)
216 	: fToken(-1)
217 {
218 }
219 
220 // =
221 /*!	\brief Privatized assignment operator to prevent usage.
222 */
223 BMessageRunner &
224 BMessageRunner::operator=(const BMessageRunner &)
225 {
226 	return *this;
227 }
228 
229 // InitData
230 /*!	\brief Initializes the BMessageRunner.
231 
232 	The success of the initialization can (and should) be asked for via
233 	InitCheck().
234 
235 	\note As soon as the last message has been sent, the message runner
236 		  becomes unusable. InitCheck() will still return \c B_OK, but
237 		  SetInterval(), SetCount() and GetInfo() will fail.
238 
239 	\param target Target of the message(s).
240 	\param message The message to be sent to the target.
241 	\param interval Period of time before the first message is sent and
242 		   between messages (if more than one shall be sent) in microseconds.
243 	\param count Specifies how many times the message shall be sent.
244 		   A value less than \c 0 for an unlimited number of repetitions.
245 	\param replyTo Target replies to the delivered message(s) shall be sent to.
246 */
247 void
248 BMessageRunner::InitData(BMessenger target, const BMessage *message,
249 						 bigtime_t interval, int32 count, BMessenger replyTo)
250 {
251 	status_t error = (message ? B_OK : B_BAD_VALUE);
252 	if (error == B_OK && count == 0)
253 		error = B_ERROR;
254 	// compose the request message
255 	BMessage request(B_REG_REGISTER_MESSAGE_RUNNER);
256 	if (error == B_OK)
257 		error = request.AddInt32("team", BPrivate::current_team());
258 	if (error == B_OK)
259 		error = request.AddMessenger("target", target);
260 	if (error == B_OK)
261 		error = request.AddMessage("message", message);
262 	if (error == B_OK)
263 		error = request.AddInt64("interval", interval);
264 	if (error == B_OK)
265 		error = request.AddInt32("count", count);
266 	if (error == B_OK)
267 		error = request.AddMessenger("reply_target", replyTo);
268 	// send the request
269 	BMessage reply;
270 	if (error == B_OK)
271 		error = BRoster::Private().SendTo(&request, &reply, false);
272 	// evaluate the reply
273 	if (error == B_OK) {
274 		if (reply.what == B_REG_SUCCESS) {
275 			if (reply.FindInt32("token", &fToken) != B_OK)
276 				error = B_ERROR;
277 		} else
278 			reply.FindInt32("error", &error);
279 	}
280 	if (error != B_OK)
281 		fToken = error;
282 }
283 
284 // SetParams
285 /*!	\brief Sets the message runner's interval and count parameters.
286 
287 	The parameters \a resetInterval and \a resetCount specify whether
288 	the interval or the count parameter respectively shall be reset.
289 
290 	At least one parameter must be set, otherwise the methods returns
291 	\c B_BAD_VALUE.
292 
293 	\param resetInterval \c true, if the interval shall be reset, \c false
294 		   otherwise -- then \a interval is ignored.
295 	\param interval The new interval in microseconds.
296 	\param resetCount \c true, if the count shall be reset, \c false
297 		   otherwise -- then \a count is ignored.
298 	\param count Specifies how many times the message shall be sent.
299 		   A value less than \c 0 for an unlimited number of repetitions.
300 	\return
301 	- \c B_OK: Everything went fine.
302 	- \c B_BAD_VALUE: The message runner is not longer valid. All the
303 	  messages that had to be sent have already been sent. Or both
304 	  \a resetInterval and \a resetCount are \c false.
305 */
306 status_t
307 BMessageRunner::SetParams(bool resetInterval, bigtime_t interval,
308 						  bool resetCount, int32 count)
309 {
310 	status_t error = ((resetInterval || resetCount) && fToken >= 0
311 					  ? B_OK : B_BAD_VALUE);
312 	// compose the request message
313 	BMessage request(B_REG_SET_MESSAGE_RUNNER_PARAMS);
314 	if (error == B_OK)
315 		error = request.AddInt32("token", fToken);
316 	if (error == B_OK && resetInterval)
317 		error = request.AddInt64("interval", interval);
318 	if (error == B_OK && resetCount)
319 		error = request.AddInt32("count", count);
320 	// send the request
321 	BMessage reply;
322 	if (error == B_OK)
323 		error = BRoster::Private().SendTo(&request, &reply, false);
324 	// evaluate the reply
325 	if (error == B_OK) {
326 		if (reply.what != B_REG_SUCCESS)
327 			reply.FindInt32("error", &error);
328 	}
329 	return error;
330 }
331 
332