1 /*
2 * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6 // Small app for testing the registrar's MessageDeliverer.
7
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13
14 #include <Application.h>
15 #include <Clipboard.h>
16 #include <Locker.h>
17 #include <Message.h>
18 #include <MessageRunner.h>
19 #include <OS.h>
20 #include <Path.h>
21 #include <Roster.h>
22 #include <String.h>
23
24 // message what codes
25 enum {
26 MSG_FILL_PORT = 'fill',
27 MSG_RUNNER = 'runn',
28 MSG_BROADCAST = 'brod',
29 };
30
31 static const uint32 sExpectedMessages[3] = {
32 B_CLIPBOARD_CHANGED,
33 MSG_RUNNER,
34 MSG_BROADCAST,
35 };
36 static const int32 sExpectedMessageCount = 3;
37 static int32 sExpectedMessageIndex = 0;
38
39 // check_expected_message
40 static
41 bool
check_expected_message(uint32 what)42 check_expected_message(uint32 what)
43 {
44 if (sExpectedMessageIndex >= sExpectedMessageCount) {
45 printf("Unexpected message '%.4s'\n", (char*)&what);
46 exit(1);
47 }
48
49 uint32 expected = sExpectedMessages[sExpectedMessageIndex++];
50 if (what != expected) {
51 printf("Unexpected message '%.4s', expected was: '%.4s'\n",
52 (char*)&what, (char*)&expected);
53 exit(1);
54 }
55
56 return (sExpectedMessageIndex == sExpectedMessageCount);
57 }
58
59
60 // TestApp
61 class TestApp : public BApplication {
62 public:
TestApp()63 TestApp()
64 : BApplication("application/x-vnd.haiku.message-deliverer-test")
65 {
66 }
67
MessageReceived(BMessage * message)68 virtual void MessageReceived(BMessage *message)
69 {
70 switch (message->what) {
71 case MSG_FILL_PORT:
72 return;
73 case MSG_RUNNER:
74 printf("MSG_RUNNER\n");
75 break;
76 case B_CLIPBOARD_CHANGED:
77 printf("B_CLIPBOARD_CHANGED\n");
78 break;
79 case MSG_BROADCAST:
80 printf("MSG_BROADCAST\n");
81 break;
82 default:
83 BApplication::MessageReceived(message);
84 return;
85 }
86
87 if (check_expected_message(message->what))
88 PostMessage(B_QUIT_REQUESTED);
89 }
90 };
91
92 // main
93 int
main(int argc,const char * const * argv)94 main(int argc, const char *const *argv)
95 {
96 // if started with parameter "broadcast", we broadcast a message and exit
97 if (argc > 1 && strcmp(argv[1], "broadcast") == 0) {
98 BMessage message(MSG_BROADCAST);
99 status_t error = be_roster->Broadcast(&message);
100 if (error != B_OK) {
101 printf("Broadcast failed: %s\n", strerror(error));
102 exit(1);
103 }
104 exit(0);
105 }
106
107 TestApp app;
108
109 // fill the looper port
110 status_t error;
111 do {
112 BMessage message(MSG_FILL_PORT);
113 error = be_app_messenger.SendMessage(&message, (BHandler*)NULL, 0LL);
114 } while (error == B_OK);
115
116 if (error != B_WOULD_BLOCK) {
117 printf("sending fill message didn't fail with B_WOULD_BLOCK: %s\n",
118 strerror(error));
119 exit(1);
120 }
121
122 // register looper for clipboard events
123 BClipboard clipboard("message deliverer test");
124 error = clipboard.StartWatching(be_app_messenger);
125 if (error != B_OK) {
126 printf("Failed to start clipboard watching: %s\n", strerror(error));
127 exit(1);
128 }
129
130 // generate a clipboard changed modification
131 if (!clipboard.Lock()) {
132 printf("Failed to lock clipboard.\n");
133 exit(1);
134 }
135 clipboard.Clear();
136 clipboard.Data()->AddString("test", "test data");
137 error = clipboard.Commit();
138 if (error != B_OK) {
139 printf("Failed to commit clipboard data: %s\n", strerror(error));
140 exit(1);
141 }
142 clipboard.Unlock();
143
144 // create a message runner
145 BMessage message(MSG_RUNNER);
146 bigtime_t interval = 100000LL;
147 BMessageRunner runner(be_app_messenger, &message, interval, 3);
148 error = runner.InitCheck();
149 if (error != B_OK) {
150 printf("Message runner initialization failed: %s\n", strerror(error));
151 exit(1);
152 }
153 snooze(5 * interval);
154
155 // broadcast a message: We do that be starting another instance of this
156 // app with parameter "broadcast". We can't do the broadcast ourselves,
157 // since the message is sent only to the other applications.
158
159 // get our app info
160 app_info appInfo;
161 error = app.GetAppInfo(&appInfo);
162 if (error != B_OK) {
163 printf("GetAppInfo() failed: %s\n", strerror(error));
164 exit(1);
165 }
166
167 // get the app path
168 BPath path;
169 error = path.SetTo(&appInfo.ref);
170 if (error != B_OK) {
171 printf("Failed to get app path: %s\n", strerror(error));
172 exit(1);
173 }
174
175 // launch...
176 BString commandLine(path.Path());
177 commandLine << " broadcast";
178 if (system(commandLine.String()) < 0) {
179 printf("Failed re-launch app for broadcasting: %s\n", strerror(errno));
180 exit(1);
181 }
182
183 // wait a bit...
184 snooze(100000);
185
186 // now start the message processing loop
187 app.Run();
188
189 return 0;
190 }
191