1 /* 2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 7 * Stephan Aßmus, superstippi@gmx.de 8 * Brian Hill, supernova@tycho.email 9 */ 10 11 12 #include <Notification.h> 13 14 #include <new> 15 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include <notification/Notifications.h> 20 21 #include <Bitmap.h> 22 #include <Message.h> 23 #include <NodeInfo.h> 24 #include <Path.h> 25 #include <Roster.h> 26 27 28 BNotification::BNotification(notification_type type) 29 : 30 BArchivable(), 31 fInitStatus(B_OK), 32 fType(type), 33 fProgress(0.f), 34 fFile(NULL), 35 fBitmap(NULL) 36 { 37 team_info teamInfo; 38 get_team_info(B_CURRENT_TEAM, &teamInfo); 39 app_info appInfo; 40 be_roster->GetRunningAppInfo(teamInfo.team, &appInfo); 41 42 int32 iconSize = B_LARGE_ICON; 43 fBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32); 44 if (fBitmap) { 45 if (BNodeInfo::GetTrackerIcon(&appInfo.ref, fBitmap, 46 icon_size(iconSize)) != B_OK) { 47 delete fBitmap; 48 fBitmap = NULL; 49 } 50 } 51 fSourceSignature = appInfo.signature; 52 BPath path(&appInfo.ref); 53 if (path.InitCheck() == B_OK) 54 fSourceName = path.Leaf(); 55 } 56 57 58 BNotification::BNotification(BMessage* archive) 59 : 60 BArchivable(archive), 61 fInitStatus(B_OK), 62 fProgress(0.0f), 63 fFile(NULL), 64 fBitmap(NULL) 65 { 66 BString appName; 67 if (archive->FindString("_appname", &appName) == B_OK) 68 fSourceName = appName; 69 70 BString signature; 71 if (archive->FindString("_signature", &signature) == B_OK) 72 fSourceSignature = signature; 73 74 int32 type; 75 if (archive->FindInt32("_type", &type) == B_OK) 76 fType = (notification_type)type; 77 else 78 fInitStatus = B_ERROR; 79 80 BString group; 81 if (archive->FindString("_group", &group) == B_OK) 82 SetGroup(group); 83 84 BString title; 85 if (archive->FindString("_title", &title) == B_OK) 86 SetTitle(title); 87 88 BString content; 89 if (archive->FindString("_content", &content) == B_OK) 90 SetContent(content); 91 92 BString messageID; 93 if (archive->FindString("_messageID", &messageID) == B_OK) 94 SetMessageID(messageID); 95 96 float progress; 97 if (type == B_PROGRESS_NOTIFICATION 98 && archive->FindFloat("_progress", &progress) == B_OK) 99 SetProgress(progress); 100 101 BString onClickApp; 102 if (archive->FindString("_onClickApp", &onClickApp) == B_OK) 103 SetOnClickApp(onClickApp); 104 105 entry_ref onClickFile; 106 if (archive->FindRef("_onClickFile", &onClickFile) == B_OK) 107 SetOnClickFile(&onClickFile); 108 109 entry_ref onClickRef; 110 int32 index = 0; 111 while (archive->FindRef("_onClickRef", index++, &onClickRef) == B_OK) 112 AddOnClickRef(&onClickRef); 113 114 BString onClickArgv; 115 index = 0; 116 while (archive->FindString("_onClickArgv", index++, &onClickArgv) == B_OK) 117 AddOnClickArg(onClickArgv); 118 119 status_t ret = B_OK; 120 BMessage icon; 121 if ((ret = archive->FindMessage("_icon", &icon)) == B_OK) { 122 BBitmap bitmap(&icon); 123 ret = bitmap.InitCheck(); 124 if (ret == B_OK) 125 ret = SetIcon(&bitmap); 126 } 127 } 128 129 130 BNotification::~BNotification() 131 { 132 delete fFile; 133 delete fBitmap; 134 135 for (int32 i = fRefs.CountItems() - 1; i >= 0; i--) 136 delete (entry_ref*)fRefs.ItemAtFast(i); 137 138 for (int32 i = fArgv.CountItems() - 1; i >= 0; i--) 139 free(fArgv.ItemAtFast(i)); 140 } 141 142 143 status_t 144 BNotification::InitCheck() const 145 { 146 return fInitStatus; 147 } 148 149 150 BArchivable* 151 BNotification::Instantiate(BMessage* archive) 152 { 153 if (validate_instantiation(archive, "BNotification")) 154 return new(std::nothrow) BNotification(archive); 155 156 return NULL; 157 } 158 159 160 status_t 161 BNotification::Archive(BMessage* archive, bool deep) const 162 { 163 status_t status = BArchivable::Archive(archive, deep); 164 165 if (status == B_OK) 166 status = archive->AddString("_appname", fSourceName); 167 168 if (status == B_OK) 169 status = archive->AddString("_signature", fSourceSignature); 170 171 if (status == B_OK) 172 status = archive->AddInt32("_type", (int32)fType); 173 174 if (status == B_OK && Group() != NULL) 175 status = archive->AddString("_group", Group()); 176 177 if (status == B_OK && Title() != NULL) 178 status = archive->AddString("_title", Title()); 179 180 if (status == B_OK && Content() != NULL) 181 status = archive->AddString("_content", Content()); 182 183 if (status == B_OK && MessageID() != NULL) 184 status = archive->AddString("_messageID", MessageID()); 185 186 if (status == B_OK && Type() == B_PROGRESS_NOTIFICATION) 187 status = archive->AddFloat("_progress", Progress()); 188 189 if (status == B_OK && OnClickApp() != NULL) 190 status = archive->AddString("_onClickApp", OnClickApp()); 191 192 if (status == B_OK && OnClickFile() != NULL) 193 status = archive->AddRef("_onClickFile", OnClickFile()); 194 195 if (status == B_OK) { 196 for (int32 i = 0; i < CountOnClickRefs(); i++) { 197 status = archive->AddRef("_onClickRef", OnClickRefAt(i)); 198 if (status != B_OK) 199 break; 200 } 201 } 202 203 if (status == B_OK) { 204 for (int32 i = 0; i < CountOnClickArgs(); i++) { 205 status = archive->AddString("_onClickArgv", OnClickArgAt(i)); 206 if (status != B_OK) 207 break; 208 } 209 } 210 211 if (status == B_OK) { 212 const BBitmap* icon = Icon(); 213 if (icon != NULL) { 214 BMessage iconArchive; 215 status = icon->Archive(&iconArchive); 216 if (status == B_OK) 217 archive->AddMessage("_icon", &iconArchive); 218 } 219 } 220 221 return status; 222 } 223 224 225 const char* 226 BNotification::SourceSignature() const 227 { 228 return fSourceSignature; 229 } 230 231 232 const char* 233 BNotification::SourceName() const 234 { 235 return fSourceName; 236 } 237 238 239 notification_type 240 BNotification::Type() const 241 { 242 return fType; 243 } 244 245 246 const char* 247 BNotification::Group() const 248 { 249 if (fGroup == "") 250 return NULL; 251 return fGroup; 252 } 253 254 255 void 256 BNotification::SetGroup(const BString& group) 257 { 258 fGroup = group; 259 } 260 261 262 const char* 263 BNotification::Title() const 264 { 265 if (fTitle == "") 266 return NULL; 267 return fTitle; 268 } 269 270 271 void 272 BNotification::SetTitle(const BString& title) 273 { 274 fTitle = title; 275 } 276 277 278 const char* 279 BNotification::Content() const 280 { 281 if (fContent == "") 282 return NULL; 283 return fContent; 284 } 285 286 287 void 288 BNotification::SetContent(const BString& content) 289 { 290 fContent = content; 291 } 292 293 294 const char* 295 BNotification::MessageID() const 296 { 297 if (fID == "") 298 return NULL; 299 return fID; 300 } 301 302 303 void 304 BNotification::SetMessageID(const BString& id) 305 { 306 fID = id; 307 } 308 309 310 float 311 BNotification::Progress() const 312 { 313 if (fType != B_PROGRESS_NOTIFICATION) 314 return -1; 315 return fProgress; 316 } 317 318 319 void 320 BNotification::SetProgress(float progress) 321 { 322 if (progress < 0) 323 fProgress = 0; 324 else if (progress > 1) 325 fProgress = 1; 326 else 327 fProgress = progress; 328 } 329 330 331 const char* 332 BNotification::OnClickApp() const 333 { 334 if (fApp == "") 335 return NULL; 336 return fApp; 337 } 338 339 340 void 341 BNotification::SetOnClickApp(const BString& app) 342 { 343 fApp = app; 344 } 345 346 347 const entry_ref* 348 BNotification::OnClickFile() const 349 { 350 return fFile; 351 } 352 353 354 status_t 355 BNotification::SetOnClickFile(const entry_ref* file) 356 { 357 delete fFile; 358 359 if (file != NULL) { 360 fFile = new(std::nothrow) entry_ref(*file); 361 if (fFile == NULL) 362 return B_NO_MEMORY; 363 } else 364 fFile = NULL; 365 366 return B_OK; 367 } 368 369 370 status_t 371 BNotification::AddOnClickRef(const entry_ref* ref) 372 { 373 if (ref == NULL) 374 return B_BAD_VALUE; 375 376 entry_ref* clonedRef = new(std::nothrow) entry_ref(*ref); 377 if (clonedRef == NULL || !fRefs.AddItem(clonedRef)) 378 return B_NO_MEMORY; 379 380 return B_OK; 381 } 382 383 384 int32 385 BNotification::CountOnClickRefs() const 386 { 387 return fRefs.CountItems(); 388 } 389 390 391 const entry_ref* 392 BNotification::OnClickRefAt(int32 index) const 393 { 394 return (entry_ref*)fRefs.ItemAt(index); 395 } 396 397 398 status_t 399 BNotification::AddOnClickArg(const BString& arg) 400 { 401 char* clonedArg = strdup(arg.String()); 402 if (clonedArg == NULL || !fArgv.AddItem(clonedArg)) 403 return B_NO_MEMORY; 404 405 return B_OK; 406 } 407 408 409 int32 410 BNotification::CountOnClickArgs() const 411 { 412 return fArgv.CountItems(); 413 } 414 415 416 const char* 417 BNotification::OnClickArgAt(int32 index) const 418 { 419 return (char*)fArgv.ItemAt(index); 420 } 421 422 423 const BBitmap* 424 BNotification::Icon() const 425 { 426 return fBitmap; 427 } 428 429 430 status_t 431 BNotification::SetIcon(const BBitmap* icon) 432 { 433 delete fBitmap; 434 435 if (icon != NULL) { 436 fBitmap = new(std::nothrow) BBitmap(icon); 437 if (fBitmap == NULL) 438 return B_NO_MEMORY; 439 return fBitmap->InitCheck(); 440 } 441 442 fBitmap = NULL; 443 return B_OK; 444 } 445 446 447 status_t 448 BNotification::Send(bigtime_t timeout) 449 { 450 BMessage msg(kNotificationMessage); 451 452 // Archive notification 453 status_t ret = Archive(&msg); 454 455 // Custom time out 456 if (ret == B_OK && timeout > 0) 457 ret = msg.AddInt64("timeout", timeout); 458 459 // Send message 460 if (ret == B_OK) { 461 BMessenger server(kNotificationServerSignature); 462 ret = server.SendMessage(&msg); 463 } 464 465 return ret; 466 } 467 468 469 void BNotification::_ReservedNotification1() {} 470 void BNotification::_ReservedNotification2() {} 471 void BNotification::_ReservedNotification3() {} 472 void BNotification::_ReservedNotification4() {} 473 void BNotification::_ReservedNotification5() {} 474 void BNotification::_ReservedNotification6() {} 475 void BNotification::_ReservedNotification7() {} 476 void BNotification::_ReservedNotification8() {} 477