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