1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold (bonefish@users.sf.net) 7 */ 8 9 10 #include <Application.h> 11 #include <AppMisc.h> 12 #include <MessageRunner.h> 13 #include <RegistrarDefs.h> 14 #include <Roster.h> 15 #include <RosterPrivate.h> 16 17 using namespace BPrivate; 18 19 20 // constructor 21 /*! \brief Creates and initializes a new BMessageRunner. 22 23 The target for replies to the delivered message(s) is \c be_app_messenger. 24 25 The success of the initialization can (and should) be asked for via 26 InitCheck(). This object will not take ownership of the \a message, you 27 may freely change or delete it after creation. 28 29 \note As soon as the last message has been sent, the message runner 30 becomes unusable. InitCheck() will still return \c B_OK, but 31 SetInterval(), SetCount() and GetInfo() will fail. 32 33 \param target Target of the message(s). 34 \param message The message to be sent to the target. 35 \param interval Period of time before the first message is sent and 36 between messages (if more than one shall be sent) in microseconds. 37 \param count Specifies how many times the message shall be sent. 38 A value less than \c 0 for an unlimited number of repetitions. 39 */ 40 BMessageRunner::BMessageRunner(BMessenger target, const BMessage *message, 41 bigtime_t interval, int32 count) 42 : fToken(-1) 43 { 44 _InitData(target, message, interval, count, be_app_messenger); 45 } 46 47 // constructor 48 /*! \brief Creates and initializes a new BMessageRunner. 49 50 This constructor version additionally allows to specify the target for 51 replies to the delivered message(s). 52 53 The success of the initialization can (and should) be asked for via 54 InitCheck(). This object will not take ownership of the \a message, you 55 may freely change or delete it after creation. 56 57 \note As soon as the last message has been sent, the message runner 58 becomes unusable. InitCheck() will still return \c B_OK, but 59 SetInterval(), SetCount() and GetInfo() will fail. 60 61 \param target Target of the message(s). 62 \param message The message to be sent to the target. 63 \param interval Period of time before the first message is sent and 64 between messages (if more than one shall be sent) in microseconds. 65 \param count Specifies how many times the message shall be sent. 66 A value less than \c 0 for an unlimited number of repetitions. 67 \param replyTo Target replies to the delivered message(s) shall be sent to. 68 */ 69 BMessageRunner::BMessageRunner(BMessenger target, const BMessage *message, 70 bigtime_t interval, int32 count, 71 BMessenger replyTo) 72 : fToken(-1) 73 { 74 _InitData(target, message, interval, count, replyTo); 75 } 76 77 78 /*! \brief Frees all resources associated with the object. 79 */ 80 BMessageRunner::~BMessageRunner() 81 { 82 if (fToken < B_OK) 83 return; 84 85 // compose the request message 86 BMessage request(B_REG_UNREGISTER_MESSAGE_RUNNER); 87 status_t error = request.AddInt32("token", fToken); 88 89 // send the request 90 BMessage reply; 91 if (error == B_OK) 92 error = BRoster::Private().SendTo(&request, &reply, false); 93 94 // ignore the reply, we can't do anything anyway 95 } 96 97 // InitCheck 98 /*! \brief Returns the status of the initialization. 99 100 \note As soon as the last message has been sent, the message runner 101 becomes unusable. InitCheck() will still return \c B_OK, but 102 SetInterval(), SetCount() and GetInfo() will fail. 103 104 \return \c B_OK, if the object is properly initialized, an error code 105 otherwise. 106 */ 107 status_t 108 BMessageRunner::InitCheck() const 109 { 110 return fToken >= 0 ? B_OK : fToken; 111 } 112 113 // SetInterval 114 /*! \brief Sets the interval of time between messages. 115 \param interval The new interval in microseconds. 116 \return 117 - \c B_OK: Everything went fine. 118 - \c B_NO_INIT: The message runner is not properly initialized. 119 - \c B_BAD_VALUE: \a interval is \c 0 or negative, or the message runner 120 has already sent all messages to be sent and has become unusable. 121 */ 122 status_t 123 BMessageRunner::SetInterval(bigtime_t interval) 124 { 125 return _SetParams(true, interval, false, 0); 126 } 127 128 // SetCount 129 /*! \brief Sets the number of times message shall be sent. 130 \param count Specifies how many times the message shall be sent. 131 A value less than \c 0 for an unlimited number of repetitions. 132 - \c B_BAD_VALUE: The message runner has already sent all messages to be 133 sent and has become unusable. 134 \return 135 - \c B_OK: Everything went fine. 136 - \c B_NO_INIT: The message runner is not properly initialized. 137 */ 138 status_t 139 BMessageRunner::SetCount(int32 count) 140 { 141 return _SetParams(false, 0, true, count); 142 } 143 144 // GetInfo 145 /*! \brief Returns the time interval between two messages and the number of 146 times the message has still to be sent. 147 148 Both parameters (\a interval and \a count) may be \c NULL. 149 150 \param interval Pointer to a pre-allocated bigtime_t variable to be set 151 to the time interval. May be \c NULL. 152 \param count Pointer to a pre-allocated int32 variable to be set 153 to the number of times the message has still to be sent. 154 May be \c NULL. 155 \return 156 - \c B_OK: Everything went fine. 157 - \c B_BAD_VALUE: The message runner is not longer valid. All the 158 messages that had to be sent have already been sent. 159 */ 160 status_t 161 BMessageRunner::GetInfo(bigtime_t *interval, int32 *count) const 162 { 163 status_t error = (fToken >= 0 ? B_OK : B_BAD_VALUE); 164 // compose the request message 165 BMessage request(B_REG_GET_MESSAGE_RUNNER_INFO); 166 if (error == B_OK) 167 error = request.AddInt32("token", fToken); 168 // send the request 169 BMessage reply; 170 if (error == B_OK) 171 error = BRoster::Private().SendTo(&request, &reply, false); 172 // evaluate the reply 173 if (error == B_OK) { 174 if (reply.what == B_REG_SUCCESS) { 175 // count 176 int32 _count; 177 if (reply.FindInt32("count", &_count) == B_OK) { 178 if (count) 179 *count = _count; 180 } else 181 error = B_ERROR; 182 // interval 183 bigtime_t _interval; 184 if (reply.FindInt64("interval", &_interval) == B_OK) { 185 if (interval) 186 *interval = _interval; 187 } else 188 error = B_ERROR; 189 } else { 190 if (reply.FindInt32("error", &error) != B_OK) 191 error = B_ERROR; 192 } 193 } 194 return error; 195 } 196 197 198 /*! \brief Creates and initializes a detached BMessageRunner. 199 200 You cannot alter the runner after the creation, and it will be deleted 201 automatically once it is done. 202 The target for replies to the delivered message(s) is \c be_app_messenger. 203 204 \param target Target of the message(s). 205 \param message The message to be sent to the target. 206 \param interval Period of time before the first message is sent and 207 between messages (if more than one shall be sent) in microseconds. 208 \param count Specifies how many times the message shall be sent. 209 A value less than \c 0 for an unlimited number of repetitions. 210 */ 211 /*static*/ status_t 212 BMessageRunner::StartSending(BMessenger target, const BMessage *message, 213 bigtime_t interval, int32 count) 214 { 215 int32 token = _RegisterRunner(target, message, interval, count, true, 216 be_app_messenger); 217 return token >= B_OK ? B_OK : token; 218 } 219 220 221 /*! \brief Creates and initializes a detached BMessageRunner. 222 223 You cannot alter the runner after the creation, and it will be deleted 224 automatically once it is done. 225 226 \param target Target of the message(s). 227 \param message The message to be sent to the target. 228 \param interval Period of time before the first message is sent and 229 between messages (if more than one shall be sent) in microseconds. 230 \param count Specifies how many times the message shall be sent. 231 A value less than \c 0 for an unlimited number of repetitions. 232 \param replyTo Target replies to the delivered message(s) shall be sent to. 233 */ 234 /*static*/ status_t 235 BMessageRunner::StartSending(BMessenger target, const BMessage *message, 236 bigtime_t interval, int32 count, BMessenger replyTo) 237 { 238 int32 token = _RegisterRunner(target, message, interval, count, true, replyTo); 239 return token >= B_OK ? B_OK : token; 240 } 241 242 243 // FBC 244 void BMessageRunner::_ReservedMessageRunner1() {} 245 void BMessageRunner::_ReservedMessageRunner2() {} 246 void BMessageRunner::_ReservedMessageRunner3() {} 247 void BMessageRunner::_ReservedMessageRunner4() {} 248 void BMessageRunner::_ReservedMessageRunner5() {} 249 void BMessageRunner::_ReservedMessageRunner6() {} 250 251 // copy constructor 252 /*! \brief Privatized copy constructor to prevent usage. 253 */ 254 BMessageRunner::BMessageRunner(const BMessageRunner &) 255 : fToken(-1) 256 { 257 } 258 259 // = 260 /*! \brief Privatized assignment operator to prevent usage. 261 */ 262 BMessageRunner & 263 BMessageRunner::operator=(const BMessageRunner &) 264 { 265 return *this; 266 } 267 268 269 /*! \brief Initializes the BMessageRunner. 270 271 The success of the initialization can (and should) be asked for via 272 InitCheck(). 273 274 \note As soon as the last message has been sent, the message runner 275 becomes unusable. InitCheck() will still return \c B_OK, but 276 SetInterval(), SetCount() and GetInfo() will fail. 277 278 \param target Target of the message(s). 279 \param message The message to be sent to the target. 280 \param interval Period of time before the first message is sent and 281 between messages (if more than one shall be sent) in microseconds. 282 \param count Specifies how many times the message shall be sent. 283 A value less than \c 0 for an unlimited number of repetitions. 284 \param replyTo Target replies to the delivered message(s) shall be sent to. 285 */ 286 void 287 BMessageRunner::_InitData(BMessenger target, const BMessage *message, 288 bigtime_t interval, int32 count, BMessenger replyTo) 289 { 290 fToken = _RegisterRunner(target, message, interval, count, false, replyTo); 291 } 292 293 294 /*! \brief Registers the BMessageRunner in the registrar. 295 296 \param target Target of the message(s). 297 \param message The message to be sent to the target. 298 \param interval Period of time before the first message is sent and 299 between messages (if more than one shall be sent) in microseconds. 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 \param replyTo Target replies to the delivered message(s) shall be sent to. 303 304 \return The token the message runner is registered with, or the error code 305 while trying to register it. 306 */ 307 /*static*/ int32 308 BMessageRunner::_RegisterRunner(BMessenger target, const BMessage *message, 309 bigtime_t interval, int32 count, bool detach, BMessenger replyTo) 310 { 311 status_t error = B_OK; 312 if (message == NULL || count == 0 || (count < 0 && detach)) 313 error = B_BAD_VALUE; 314 315 // compose the request message 316 BMessage request(B_REG_REGISTER_MESSAGE_RUNNER); 317 if (error == B_OK) 318 error = request.AddInt32("team", BPrivate::current_team()); 319 if (error == B_OK) 320 error = request.AddMessenger("target", target); 321 if (error == B_OK) 322 error = request.AddMessage("message", message); 323 if (error == B_OK) 324 error = request.AddInt64("interval", interval); 325 if (error == B_OK) 326 error = request.AddInt32("count", count); 327 if (error == B_OK) 328 error = request.AddMessenger("reply_target", replyTo); 329 330 // send the request 331 BMessage reply; 332 if (error == B_OK) 333 error = BRoster::Private().SendTo(&request, &reply, false); 334 335 int32 token; 336 337 // evaluate the reply 338 if (error == B_OK) { 339 if (reply.what == B_REG_SUCCESS) { 340 if (reply.FindInt32("token", &token) != B_OK) 341 error = B_ERROR; 342 } else { 343 if (reply.FindInt32("error", &error) != B_OK) 344 error = B_ERROR; 345 } 346 } 347 348 if (error == B_OK) 349 return token; 350 351 return error; 352 } 353 354 355 /*! \brief Sets the message runner's interval and count parameters. 356 357 The parameters \a resetInterval and \a resetCount specify whether 358 the interval or the count parameter respectively shall be reset. 359 360 At least one parameter must be set, otherwise the methods returns 361 \c B_BAD_VALUE. 362 363 \param resetInterval \c true, if the interval shall be reset, \c false 364 otherwise -- then \a interval is ignored. 365 \param interval The new interval in microseconds. 366 \param resetCount \c true, if the count shall be reset, \c false 367 otherwise -- then \a count is ignored. 368 \param count Specifies how many times the message shall be sent. 369 A value less than \c 0 for an unlimited number of repetitions. 370 \return 371 - \c B_OK: Everything went fine. 372 - \c B_BAD_VALUE: The message runner is not longer valid. All the 373 messages that had to be sent have already been sent. Or both 374 \a resetInterval and \a resetCount are \c false. 375 */ 376 status_t 377 BMessageRunner::_SetParams(bool resetInterval, bigtime_t interval, 378 bool resetCount, int32 count) 379 { 380 if ((!resetInterval && !resetCount) || fToken < 0) 381 return B_BAD_VALUE; 382 383 // compose the request message 384 BMessage request(B_REG_SET_MESSAGE_RUNNER_PARAMS); 385 status_t error = request.AddInt32("token", fToken); 386 if (error == B_OK && resetInterval) 387 error = request.AddInt64("interval", interval); 388 if (error == B_OK && resetCount) 389 error = request.AddInt32("count", count); 390 391 // send the request 392 BMessage reply; 393 if (error == B_OK) 394 error = BRoster::Private().SendTo(&request, &reply, false); 395 396 // evaluate the reply 397 if (error == B_OK) { 398 if (reply.what != B_REG_SUCCESS) { 399 if (reply.FindInt32("error", &error) != B_OK) 400 error = B_ERROR; 401 } 402 } 403 return error; 404 } 405 406