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
BNotification(notification_type type)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
BNotification(BMessage * archive)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
~BNotification()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
InitCheck() const144 BNotification::InitCheck() const
145 {
146 return fInitStatus;
147 }
148
149
150 BArchivable*
Instantiate(BMessage * archive)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
Archive(BMessage * archive,bool deep) const161 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*
SourceSignature() const226 BNotification::SourceSignature() const
227 {
228 return fSourceSignature;
229 }
230
231
232 const char*
SourceName() const233 BNotification::SourceName() const
234 {
235 return fSourceName;
236 }
237
238
239 notification_type
Type() const240 BNotification::Type() const
241 {
242 return fType;
243 }
244
245
246 const char*
Group() const247 BNotification::Group() const
248 {
249 if (fGroup == "")
250 return NULL;
251 return fGroup;
252 }
253
254
255 void
SetGroup(const BString & group)256 BNotification::SetGroup(const BString& group)
257 {
258 fGroup = group;
259 }
260
261
262 const char*
Title() const263 BNotification::Title() const
264 {
265 if (fTitle == "")
266 return NULL;
267 return fTitle;
268 }
269
270
271 void
SetTitle(const BString & title)272 BNotification::SetTitle(const BString& title)
273 {
274 fTitle = title;
275 }
276
277
278 const char*
Content() const279 BNotification::Content() const
280 {
281 if (fContent == "")
282 return NULL;
283 return fContent;
284 }
285
286
287 void
SetContent(const BString & content)288 BNotification::SetContent(const BString& content)
289 {
290 fContent = content;
291 }
292
293
294 const char*
MessageID() const295 BNotification::MessageID() const
296 {
297 if (fID == "")
298 return NULL;
299 return fID;
300 }
301
302
303 void
SetMessageID(const BString & id)304 BNotification::SetMessageID(const BString& id)
305 {
306 fID = id;
307 }
308
309
310 float
Progress() const311 BNotification::Progress() const
312 {
313 if (fType != B_PROGRESS_NOTIFICATION)
314 return -1;
315 return fProgress;
316 }
317
318
319 void
SetProgress(float progress)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*
OnClickApp() const332 BNotification::OnClickApp() const
333 {
334 if (fApp == "")
335 return NULL;
336 return fApp;
337 }
338
339
340 void
SetOnClickApp(const BString & app)341 BNotification::SetOnClickApp(const BString& app)
342 {
343 fApp = app;
344 }
345
346
347 const entry_ref*
OnClickFile() const348 BNotification::OnClickFile() const
349 {
350 return fFile;
351 }
352
353
354 status_t
SetOnClickFile(const entry_ref * file)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
AddOnClickRef(const entry_ref * ref)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
CountOnClickRefs() const385 BNotification::CountOnClickRefs() const
386 {
387 return fRefs.CountItems();
388 }
389
390
391 const entry_ref*
OnClickRefAt(int32 index) const392 BNotification::OnClickRefAt(int32 index) const
393 {
394 return (entry_ref*)fRefs.ItemAt(index);
395 }
396
397
398 status_t
AddOnClickArg(const BString & arg)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
CountOnClickArgs() const410 BNotification::CountOnClickArgs() const
411 {
412 return fArgv.CountItems();
413 }
414
415
416 const char*
OnClickArgAt(int32 index) const417 BNotification::OnClickArgAt(int32 index) const
418 {
419 return (char*)fArgv.ItemAt(index);
420 }
421
422
423 const BBitmap*
Icon() const424 BNotification::Icon() const
425 {
426 return fBitmap;
427 }
428
429
430 status_t
SetIcon(const BBitmap * icon)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
Send(bigtime_t timeout)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
_ReservedNotification1()469 void BNotification::_ReservedNotification1() {}
_ReservedNotification2()470 void BNotification::_ReservedNotification2() {}
_ReservedNotification3()471 void BNotification::_ReservedNotification3() {}
_ReservedNotification4()472 void BNotification::_ReservedNotification4() {}
_ReservedNotification5()473 void BNotification::_ReservedNotification5() {}
_ReservedNotification6()474 void BNotification::_ReservedNotification6() {}
_ReservedNotification7()475 void BNotification::_ReservedNotification7() {}
_ReservedNotification8()476 void BNotification::_ReservedNotification8() {}
477