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 reply.FindInt32("error", &error); 191 } 192 return error; 193 } 194 195 196 /*! \brief Creates and initializes a detached BMessageRunner. 197 198 You cannot alter the runner after the creation, and it will be deleted 199 automatically once it is done. 200 The target for replies to the delivered message(s) is \c be_app_messenger. 201 202 \param target Target of the message(s). 203 \param message The message to be sent to the target. 204 \param interval Period of time before the first message is sent and 205 between messages (if more than one shall be sent) in microseconds. 206 \param count Specifies how many times the message shall be sent. 207 A value less than \c 0 for an unlimited number of repetitions. 208 */ 209 /*static*/ status_t 210 BMessageRunner::StartSending(BMessenger target, const BMessage *message, 211 bigtime_t interval, int32 count) 212 { 213 int32 token = _RegisterRunner(target, message, interval, count, true, 214 be_app_messenger); 215 return token >= B_OK ? B_OK : token; 216 } 217 218 219 /*! \brief Creates and initializes a detached BMessageRunner. 220 221 You cannot alter the runner after the creation, and it will be deleted 222 automatically once it is done. 223 224 \param target Target of the message(s). 225 \param message The message to be sent to the target. 226 \param interval Period of time before the first message is sent and 227 between messages (if more than one shall be sent) in microseconds. 228 \param count Specifies how many times the message shall be sent. 229 A value less than \c 0 for an unlimited number of repetitions. 230 \param replyTo Target replies to the delivered message(s) shall be sent to. 231 */ 232 /*static*/ status_t 233 BMessageRunner::StartSending(BMessenger target, const BMessage *message, 234 bigtime_t interval, int32 count, BMessenger replyTo) 235 { 236 int32 token = _RegisterRunner(target, message, interval, count, true, replyTo); 237 return token >= B_OK ? B_OK : token; 238 } 239 240 241 // FBC 242 void BMessageRunner::_ReservedMessageRunner1() {} 243 void BMessageRunner::_ReservedMessageRunner2() {} 244 void BMessageRunner::_ReservedMessageRunner3() {} 245 void BMessageRunner::_ReservedMessageRunner4() {} 246 void BMessageRunner::_ReservedMessageRunner5() {} 247 void BMessageRunner::_ReservedMessageRunner6() {} 248 249 // copy constructor 250 /*! \brief Privatized copy constructor to prevent usage. 251 */ 252 BMessageRunner::BMessageRunner(const BMessageRunner &) 253 : fToken(-1) 254 { 255 } 256 257 // = 258 /*! \brief Privatized assignment operator to prevent usage. 259 */ 260 BMessageRunner & 261 BMessageRunner::operator=(const BMessageRunner &) 262 { 263 return *this; 264 } 265 266 267 /*! \brief Initializes the BMessageRunner. 268 269 The success of the initialization can (and should) be asked for via 270 InitCheck(). 271 272 \note As soon as the last message has been sent, the message runner 273 becomes unusable. InitCheck() will still return \c B_OK, but 274 SetInterval(), SetCount() and GetInfo() will fail. 275 276 \param target Target of the message(s). 277 \param message The message to be sent to the target. 278 \param interval Period of time before the first message is sent and 279 between messages (if more than one shall be sent) in microseconds. 280 \param count Specifies how many times the message shall be sent. 281 A value less than \c 0 for an unlimited number of repetitions. 282 \param replyTo Target replies to the delivered message(s) shall be sent to. 283 */ 284 void 285 BMessageRunner::_InitData(BMessenger target, const BMessage *message, 286 bigtime_t interval, int32 count, BMessenger replyTo) 287 { 288 fToken = _RegisterRunner(target, message, interval, count, false, replyTo); 289 } 290 291 292 /*! \brief Registers the BMessageRunner in the registrar. 293 294 \param target Target of the message(s). 295 \param message The message to be sent to the target. 296 \param interval Period of time before the first message is sent and 297 between messages (if more than one shall be sent) in microseconds. 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 \param replyTo Target replies to the delivered message(s) shall be sent to. 301 302 \return The token the message runner is registered with, or the error code 303 while trying to register it. 304 */ 305 /*static*/ int32 306 BMessageRunner::_RegisterRunner(BMessenger target, const BMessage *message, 307 bigtime_t interval, int32 count, bool detach, BMessenger replyTo) 308 { 309 status_t error = B_OK; 310 if (message == NULL || count == 0 || (count < 0 && detach)) 311 error = B_BAD_VALUE; 312 313 // compose the request message 314 BMessage request(B_REG_REGISTER_MESSAGE_RUNNER); 315 if (error == B_OK) 316 error = request.AddInt32("team", BPrivate::current_team()); 317 if (error == B_OK) 318 error = request.AddMessenger("target", target); 319 if (error == B_OK) 320 error = request.AddMessage("message", message); 321 if (error == B_OK) 322 error = request.AddInt64("interval", interval); 323 if (error == B_OK) 324 error = request.AddInt32("count", count); 325 if (error == B_OK) 326 error = request.AddMessenger("reply_target", replyTo); 327 328 // send the request 329 BMessage reply; 330 if (error == B_OK) 331 error = BRoster::Private().SendTo(&request, &reply, false); 332 333 int32 token; 334 335 // evaluate the reply 336 if (error == B_OK) { 337 if (reply.what == B_REG_SUCCESS) { 338 if (reply.FindInt32("token", &token) != B_OK) 339 error = B_ERROR; 340 } else 341 reply.FindInt32("error", &error); 342 } 343 344 if (error == B_OK) 345 return token; 346 347 return error; 348 } 349 350 351 /*! \brief Sets the message runner's interval and count parameters. 352 353 The parameters \a resetInterval and \a resetCount specify whether 354 the interval or the count parameter respectively shall be reset. 355 356 At least one parameter must be set, otherwise the methods returns 357 \c B_BAD_VALUE. 358 359 \param resetInterval \c true, if the interval shall be reset, \c false 360 otherwise -- then \a interval is ignored. 361 \param interval The new interval in microseconds. 362 \param resetCount \c true, if the count shall be reset, \c false 363 otherwise -- then \a count is ignored. 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 \return 367 - \c B_OK: Everything went fine. 368 - \c B_BAD_VALUE: The message runner is not longer valid. All the 369 messages that had to be sent have already been sent. Or both 370 \a resetInterval and \a resetCount are \c false. 371 */ 372 status_t 373 BMessageRunner::_SetParams(bool resetInterval, bigtime_t interval, 374 bool resetCount, int32 count) 375 { 376 if ((!resetInterval && !resetCount) || fToken < 0) 377 return B_BAD_VALUE; 378 379 // compose the request message 380 BMessage request(B_REG_SET_MESSAGE_RUNNER_PARAMS); 381 status_t error = request.AddInt32("token", fToken); 382 if (error == B_OK && resetInterval) 383 error = request.AddInt64("interval", interval); 384 if (error == B_OK && resetCount) 385 error = request.AddInt32("count", count); 386 387 // send the request 388 BMessage reply; 389 if (error == B_OK) 390 error = BRoster::Private().SendTo(&request, &reply, false); 391 392 // evaluate the reply 393 if (error == B_OK) { 394 if (reply.what != B_REG_SUCCESS) 395 reply.FindInt32("error", &error); 396 } 397 return error; 398 } 399 400