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 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: 63 TestApp() 64 : BApplication("application/x-vnd.haiku.message-deliverer-test") 65 { 66 } 67 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 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