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