Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / bin / notify.cpp
blobc2030b6404c4f2ea1a908a3d405eb4b3c514a7be
1 /*
2 * Copyright 2010, Haiku, Inc. All rights reserved.
3 * Copyright 2008, Pier Luigi Fiorini.
4 * Distributed under the terms of the MIT License.
6 * Authors:
7 * Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
8 * Stephan Aßmus <superstippi@gmx.de>
9 */
11 #include <stdio.h>
12 #include <stdlib.h>
14 #include <Application.h>
15 #include <Bitmap.h>
16 #include <IconUtils.h>
17 #include <List.h>
18 #include <Mime.h>
19 #include <Notification.h>
20 #include <Path.h>
21 #include <TranslationUtils.h>
23 const char* kSignature = "application/x-vnd.Haiku-notify";
24 const char* kSmallIconAttribute = "BEOS:M:STD_ICON";
25 const char* kLargeIconAttribute = "BEOS:L:STD_ICON";
26 const char* kIconAttribute = "BEOS:ICON";
28 const char *kTypeNames[] = {
29 "information",
30 "important",
31 "error",
32 "progress",
33 NULL
36 const int32 kErrorInitFail = 127;
37 const int32 kErrorArgumentsFail = 126;
39 class NotifyApp : public BApplication {
40 public:
41 NotifyApp();
42 virtual ~NotifyApp();
44 virtual void ReadyToRun();
45 virtual void ArgvReceived(int32 argc, char** argv);
47 bool HasGoodArguments() const
48 { return fHasGoodArguments; }
50 private:
51 bool fHasGoodArguments;
52 notification_type fType;
53 BString fGroup;
54 BString fTitle;
55 BString fMsgId;
56 float fProgress;
57 bigtime_t fTimeout;
58 BString fIconFile;
59 entry_ref fFileRef;
60 BString fContent;
61 BString fOnClickApp;
62 bool fHasFile;
63 entry_ref fFile;
64 BList* fRefs;
65 BList* fArgv;
67 void _Usage() const;
68 BBitmap* _GetBitmap(const entry_ref* ref) const;
72 NotifyApp::NotifyApp()
74 BApplication(kSignature),
75 fHasGoodArguments(false),
76 fType(B_INFORMATION_NOTIFICATION),
77 fProgress(0.0f),
78 fTimeout(-1),
79 fHasFile(false)
81 fRefs = new BList();
82 fArgv = new BList();
86 NotifyApp::~NotifyApp()
88 for (int32 i = 0; void* item = fRefs->ItemAt(i); i++)
89 delete (BEntry*)item;
90 delete fRefs;
92 for (int32 i = 0; void* item = fArgv->ItemAt(i); i++)
93 delete (BString*)item;
94 delete fArgv;
98 void
99 NotifyApp::ArgvReceived(int32 argc, char** argv)
101 const uint32 kArgCount = argc - 1;
102 uint32 index = 1;
104 // Look for valid options
105 for (; index <= kArgCount; ++index) {
106 if (argv[index][0] == '-' && argv[index][1] == '-') {
107 const char* option = argv[index] + 2;
109 if (++index > kArgCount) {
110 // No argument to option
111 fprintf(stderr, "Missing argument to option --%s\n\n", option);
112 return;
115 const char* argument = argv[index];
117 if (strcmp(option, "type") == 0) {
118 for (int32 i = 0; kTypeNames[i]; i++) {
119 if (strncmp(kTypeNames[i], argument, strlen(argument)) == 0)
120 fType = (notification_type)i;
122 } else if (strcmp(option, "group") == 0)
123 fGroup = argument;
124 else if (strcmp(option, "title") == 0)
125 fTitle = argument;
126 else if (strcmp(option, "messageID") == 0)
127 fMsgId = argument;
128 else if (strcmp(option, "progress") == 0)
129 fProgress = atof(argument);
130 else if (strcmp(option, "timeout") == 0)
131 fTimeout = atol(argument) * 1000000;
132 else if (strcmp(option, "icon") == 0) {
133 fIconFile = argument;
135 if (get_ref_for_path(fIconFile.String(), &fFileRef) < B_OK) {
136 fprintf(stderr, "Bad icon path!\n\n");
137 return;
139 } else if (strcmp(option, "onClickApp") == 0)
140 fOnClickApp = argument;
141 else if (strcmp(option, "onClickFile") == 0) {
142 if (get_ref_for_path(argument, &fFile) != B_OK) {
143 fprintf(stderr, "Bad path for --onClickFile!\n\n");
144 return;
147 fHasFile = true;
148 } else if (strcmp(option, "onClickRef") == 0) {
149 entry_ref ref;
151 if (get_ref_for_path(argument, &ref) != B_OK) {
152 fprintf(stderr, "Bad path for --onClickRef!\n\n");
153 return;
156 fRefs->AddItem(new BEntry(&ref));
157 } else if (strcmp(option, "onClickArgv") == 0)
158 fArgv->AddItem(new BString(argument));
159 else {
160 // Unrecognized option
161 fprintf(stderr, "Unrecognized option --%s\n\n", option);
162 return;
164 } else {
165 // Option doesn't start with '--'
166 break;
169 if (index == kArgCount) {
170 // No text argument provided, only '--' arguments
171 fprintf(stderr, "Missing message argument!\n\n");
172 return;
176 fContent = argv[index];
177 fHasGoodArguments = true;
180 void
181 NotifyApp::_Usage() const
183 fprintf(stderr, "Usage: notify [OPTION]... [MESSAGE]\n"
184 "Send notifications to notification_server.\n"
185 " --type <type>\tNotification type,\n"
186 " \t <type> - \"information\" is assumed by default: ");
188 for (int32 i = 0; kTypeNames[i]; i++)
189 fprintf(stderr, kTypeNames[i + 1] ? "%s|" : "%s\n", kTypeNames[i]);
191 fprintf(stderr,
192 " --group <group>\tGroup\n"
193 " --title <title>\tMessage title\n"
194 " --messageID <msg id>\tMessage ID\n"
195 " --progress <float>\tProgress, value between 0.0 and 1.0 - if type is set to progress\n"
196 " --timeout <secs>\tSpecify timeout\n"
197 " --onClickApp <signature>\tApplication to open when notification is clicked\n"
198 " --onClickFile <fullpath>\tFile to open when notification is clicked\n"
199 " --onClickRef <fullpath>\tFile to open with the application when notification is clicked\n"
200 " --onClickArgv <arg>\tArgument to the application when notification is clicked\n"
201 " --icon <icon file> Icon\n");
205 BBitmap*
206 NotifyApp::_GetBitmap(const entry_ref* ref) const
208 BBitmap* bitmap = NULL;
210 // First try by contents
211 bitmap = BTranslationUtils::GetBitmap(ref);
212 if (bitmap)
213 return bitmap;
215 // Then, try reading its attribute
216 BNode node(BPath(ref).Path());
217 bitmap = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1,
218 (float)B_LARGE_ICON - 1), B_RGBA32);
219 if (BIconUtils::GetIcon(&node, kIconAttribute, kSmallIconAttribute,
220 kLargeIconAttribute, B_LARGE_ICON, bitmap) != B_OK) {
221 delete bitmap;
222 bitmap = NULL;
225 return bitmap;
229 void
230 NotifyApp::ReadyToRun()
232 if (HasGoodArguments()) {
233 BNotification notification(fType);
234 if (fGroup != "")
235 notification.SetGroup(fGroup);
236 if (fTitle != "")
237 notification.SetTitle(fTitle);
238 if (fContent != "")
239 notification.SetContent(fContent);
241 if (fMsgId != "")
242 notification.SetMessageID(fMsgId);
244 if (fType == B_PROGRESS_NOTIFICATION)
245 notification.SetProgress(fProgress);
247 if (fIconFile != "") {
248 BBitmap* bitmap = _GetBitmap(&fFileRef);
249 if (bitmap) {
250 notification.SetIcon(bitmap);
251 delete bitmap;
255 if (fOnClickApp != "")
256 notification.SetOnClickApp(fOnClickApp);
258 if (fHasFile)
259 notification.SetOnClickFile(&fFile);
261 for (int32 i = 0; void* item = fRefs->ItemAt(i); i++) {
262 BEntry* entry = (BEntry*)item;
264 entry_ref ref;
265 if (entry->GetRef(&ref) == B_OK)
266 notification.AddOnClickRef(&ref);
269 for (int32 i = 0; void* item = fArgv->ItemAt(i); i++) {
270 BString* arg = (BString*)item;
271 notification.AddOnClickArg(arg->String());
274 status_t ret = notification.Send(fTimeout);
275 if (ret != B_OK) {
276 fprintf(stderr, "Failed to deliver notification: %s\n",
277 strerror(ret));
279 } else
280 _Usage();
282 Quit();
287 main(int argc, char** argv)
289 NotifyApp app;
290 if (app.InitCheck() != B_OK)
291 return kErrorInitFail;
293 app.Run();
294 if (!app.HasGoodArguments())
295 return kErrorArgumentsFail;
297 return 0;