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