xref: /haiku/src/tests/servers/input/msgspy/MsgSpy.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 //-------------------------------------------------------------------------
2 // Handy InputFilter that dumps all Messages to a file.
3 //-------------------------------------------------------------------------
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 
8 #include <Debug.h>
9 #include <List.h>
10 #include <File.h>
11 #include <Message.h>
12 #include <String.h>
13 #include <OS.h>
14 
15 #include <add-ons/input_server/InputServerFilter.h>
16 
17 extern "C" _EXPORT BInputServerFilter* instantiate_input_filter();
18 
19 class MsgSpy : public BInputServerFilter
20 {
21 public:
22 	         MsgSpy();
23 	virtual ~MsgSpy();
24 
25     virtual status_t      InitCheck(void);
26 	virtual	filter_result Filter(BMessage *message, BList *outList);
27 private:
28 	const char* MapWhatToString(uint32 w);
29 	void        OutputMsgField(const char*  fieldName,
30 	                           const uint32 rawType,
31                                int          rawCount,
32                                const void*  rawData);
33 
34     status_t m_status;
35     BFile*   m_outfile;
36 };
37 
38 //-------------------------------------------------------------------------
39 // Create a new MsgSpy instance and return it to the caller.
40 //-------------------------------------------------------------------------
41 BInputServerFilter* instantiate_input_filter()
42 {
43 	return (new MsgSpy() );
44 }
45 
46 
47 //-------------------------------------------------------------------------
48 //-------------------------------------------------------------------------
49 MsgSpy::MsgSpy()
50 {
51     // Create the output file and return its status.
52     m_outfile = new BFile("/boot/home/MsgSpy.output", B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
53     //m_status = m_outfile->InitCheck();
54     m_status = B_OK;
55 }
56 
57 //-------------------------------------------------------------------------
58 //-------------------------------------------------------------------------
59 MsgSpy::~MsgSpy()
60 {
61     if (NULL != m_outfile)
62     {
63         // Close and destroy the output file.
64         delete m_outfile;
65     }
66 }
67 
68 //-------------------------------------------------------------------------
69 //-------------------------------------------------------------------------
70 status_t MsgSpy::InitCheck(void)
71 {
72 	return m_status;
73 }
74 
75 //-------------------------------------------------------------------------
76 //-------------------------------------------------------------------------
77 filter_result MsgSpy::Filter(BMessage *message, BList *outList)
78 {
79     char*       field_name;
80     uint32      field_type;
81     int32       field_count;
82     const void* field_data;
83     ssize_t     field_data_bytes;
84 	char        msg_buffer  [1024];
85 
86 	// Print out the message constant (what).
87 	sprintf(msg_buffer, "%s\n", MapWhatToString(message->what) );
88     m_outfile->Write(msg_buffer, strlen(msg_buffer) );
89 
90     // Display each field in the message.
91 	sprintf(msg_buffer, "{\n");
92     m_outfile->Write(msg_buffer, strlen(msg_buffer) );
93 	for (int32 i = 0;  B_OK == message->GetInfo(B_ANY_TYPE,
94 	                                            i,
95 	                                            &field_name,
96 	                                            &field_type,
97 	                                            &field_count);  i++)
98 	{
99 		message->FindData(field_name, field_type, &field_data, &field_data_bytes);
100 		OutputMsgField(field_name, field_type, field_count, field_data);
101 	}
102 	sprintf(msg_buffer, "}\n");
103     m_outfile->Write(msg_buffer, strlen(msg_buffer) );
104 
105 	return (B_DISPATCH_MESSAGE);
106 }
107 
108 //-------------------------------------------------------------------------
109 //-------------------------------------------------------------------------
110 const char* MsgSpy::MapWhatToString(uint32 w)
111 {
112     const char* s;
113 	switch (w)
114 	{
115 		// Pointing device event messages.
116 		case B_MOUSE_DOWN:					s = "B_MOUSE_DOWN";					break;
117 		case B_MOUSE_UP:					s = "B_MOUSE_UP";					break;
118 		case B_MOUSE_MOVED:					s = "B_MOUSE_MOVED";				break;
119 		case B_MOUSE_WHEEL_CHANGED:				s = "B_MOUSE_WHEEL_CHANGED";			break;
120 
121 		// Keyboard device event messages.
122 		case B_KEY_DOWN:					s = "B_KEY_DOWN";					break;
123 		case B_UNMAPPED_KEY_DOWN:			s = "B_UNMAPPED_KEY_DOWN";			break;
124 		case B_KEY_UP:						s = "B_KEY_UP";						break;
125 		case B_UNMAPPED_KEY_UP:				s = "B_UNMAPPED_KEY_UP";			break;
126 		case B_MODIFIERS_CHANGED:			s = "B_MODIFIERS_CHANGED";			break;
127 
128 		case B_INPUT_METHOD_EVENT:			s = "B_INPUT_METHOD_EVENT";			break;
129 		default:							s = "UNKNOWN_MESSAGE";				break;
130 	}
131 	return s;
132 }
133 
134 //-------------------------------------------------------------------------
135 //-------------------------------------------------------------------------
136 void MsgSpy::OutputMsgField(const char*  fieldName,
137                             const uint32 rawType,
138                             int          rawCount,
139                             const void*  rawData)
140 {
141 	char        msg_buffer   [1024];
142 	char        value_buffer [256];
143 	BString     field_data;
144     const char* field_type;
145     const int   field_count  = rawCount;
146     const char* separator;
147 
148 	switch (rawType)
149 	{
150 		case B_CHAR_TYPE:
151 		{
152 			field_type = "B_CHAR_TYPE";
153 			field_data << "{ ";
154 			for (const char* data_ptr = (const char*)rawData;
155 				rawCount > 0;
156 				rawCount--, data_ptr++)
157 			{
158 				separator = (1 < rawCount) ? ", " : " }";
159 				field_data << *data_ptr << separator;
160 			}
161 			break;
162 		}
163 
164 		case B_INT8_TYPE:
165 		{
166 			field_type = "B_INT8_TYPE";
167 			field_data << "{ ";
168 			for (const int8* data_ptr = (const int8*)rawData;
169 				rawCount > 0;
170 				rawCount--, data_ptr++)
171 			{
172 				separator = (1 < rawCount) ? ", " : " }";
173 				field_data << *data_ptr << separator;
174 			}
175 			break;
176 		}
177 
178 		case B_INT16_TYPE:
179 		{
180 			field_type = "B_INT16_TYPE";
181 			field_data << "{ ";
182 			for (const int16* data_ptr = (const int16*)rawData;
183 				rawCount > 0;
184 				rawCount--, data_ptr++)
185 			{
186 				separator = (1 < rawCount) ? ", " : " }";
187 				field_data << *data_ptr << separator;
188 			}
189 			break;
190 		}
191 
192 		case B_INT32_TYPE:
193 		{
194 			field_type = "B_INT32_TYPE";
195 			field_data << "{ ";
196 			for (const int32* data_ptr = (const int32*)rawData;
197 				rawCount > 0;
198 				rawCount--, data_ptr++)
199 			{
200 				separator = (1 < rawCount) ? ", " : " }";
201 				field_data << *data_ptr << separator;
202 			}
203 			break;
204 		}
205 
206 		case B_INT64_TYPE:
207 		{
208 			field_type = "B_INT64_TYPE";
209 			field_data << "{ ";
210 			for (const int64* data_ptr = (const int64*)rawData;
211 				rawCount > 0;
212 				rawCount--, data_ptr++)
213 			{
214 				separator = (1 < rawCount) ? ", " : " }";
215 				field_data << *data_ptr << separator;
216 			}
217 			break;
218 		}
219 
220 		case B_UINT8_TYPE:
221 		{
222 			field_type = "B_UINT8_TYPE";
223 			field_data << "{ ";
224 			for (const uint8* data_ptr = (const uint8*)rawData;
225 				rawCount > 0;
226 				rawCount--, data_ptr++)
227 			{
228 				separator = (1 < rawCount) ? ", " : " }";
229 				field_data << (uint32)(*data_ptr) << separator;
230 			}
231 			break;
232 		}
233 
234 		case B_UINT16_TYPE:
235 		{
236 			field_type = "B_UINT16_TYPE";
237 			field_data << "{ ";
238 			for (const uint16* data_ptr = (const uint16*)rawData;
239 				rawCount > 0;
240 				rawCount--, data_ptr++)
241 			{
242 				separator = (1 < rawCount) ? ", " : " }";
243 				field_data << (uint32)(*data_ptr) << separator;
244 			}
245 			break;
246 		}
247 
248 		case B_UINT32_TYPE:
249 		{
250 			field_type = "B_UINT32_TYPE";
251 			field_data << "{ ";
252 			for (const uint32* data_ptr = (const uint32*)rawData;
253 				rawCount > 0;
254 				rawCount--, data_ptr++)
255 			{
256 				separator = (1 < rawCount) ? ", " : " }";
257 				field_data << *data_ptr << separator;
258 			}
259 			break;
260 		}
261 
262 		case B_UINT64_TYPE:
263 		{
264 			field_type = "B_UINT64_TYPE";
265 			field_data << "{ ";
266 			for (const uint64* data_ptr = (const uint64*)rawData;
267 				rawCount > 0;
268 				rawCount--, data_ptr++)
269 			{
270 				separator = (1 < rawCount) ? ", " : " }";
271 				field_data << *data_ptr << separator;
272 			}
273 			break;
274 		}
275 
276 		case B_FLOAT_TYPE:
277 		{
278 			field_type = "B_FLOAT_TYPE";
279 			field_data << "{ ";
280 			for (const float* data_ptr = (const float*)rawData;
281 				rawCount > 0;
282 				rawCount--, data_ptr++)
283 			{
284 				separator = (1 < rawCount) ? ", " : " }";
285 				field_data << *data_ptr << separator;
286 			}
287 			break;
288 		}
289 
290 		case B_DOUBLE_TYPE:
291 		{
292 			field_type = "B_DOUBLE_TYPE";
293 			field_data << "{ ";
294 			for (const double* data_ptr = (const double*)rawData;
295 				rawCount > 0;
296 				rawCount--, data_ptr++)
297 			{
298 				separator = (1 < rawCount) ? ", " : " }";
299 				sprintf(value_buffer, "%f", *data_ptr);
300 				field_data << value_buffer << separator;
301 			}
302 			break;
303 		}
304 
305 		case B_BOOL_TYPE:
306 		{
307 			field_type = "B_BOOL_TYPE";
308 			field_data << "{ ";
309 			for (const bool* data_ptr = (const bool*)rawData;
310 				rawCount > 0;
311 				rawCount--, data_ptr++)
312 			{
313 				separator = (1 < rawCount) ? ", " : " }";
314 				sprintf(value_buffer, "%s", (true == *data_ptr) ? "true" : "false");
315 				field_data << value_buffer << separator;
316 			}
317 			break;
318 		}
319 
320 		case B_OFF_T_TYPE:
321 		{
322 			field_type = "B_OFF_T_TYPE";
323 			field_data << "{ ";
324 			for (const off_t* data_ptr = (const off_t*)rawData;
325 				rawCount > 0;
326 				rawCount--, data_ptr++)
327 			{
328 				separator = (1 < rawCount) ? ", " : " }";
329 				field_data << *data_ptr << separator;
330 			}
331 			break;
332 		}
333 
334 		case B_SIZE_T_TYPE:
335 		{
336 			field_type = "B_SIZE_T_TYPE";
337 			field_data << "{ ";
338 			for (const size_t* data_ptr = (const size_t*)rawData;
339 				rawCount > 0;
340 				rawCount--, data_ptr++)
341 			{
342 				separator = (1 < rawCount) ? ", " : " }";
343 				field_data << *data_ptr << separator;
344 			}
345 			break;
346 		}
347 
348 		case B_SSIZE_T_TYPE:
349 		{
350 			field_type = "B_SSIZE_T_TYPE";
351 			field_data << "{ ";
352 			for (const ssize_t* data_ptr = (const ssize_t*)rawData;
353 				rawCount > 0;
354 				rawCount--, data_ptr++)
355 			{
356 				separator = (1 < rawCount) ? ", " : " }";
357 				field_data << *data_ptr << separator;
358 			}
359 			break;
360 		}
361 
362 		case B_POINTER_TYPE:
363 		{
364 			field_type = "B_POINTER_TYPE";
365 			break;
366 		}
367 
368 		case B_OBJECT_TYPE:
369 		{
370 			field_type = "B_OBJECT_TYPE";
371 			break;
372 		}
373 
374 		case B_MESSAGE_TYPE:
375 		{
376 			field_type = "B_MESSAGE_TYPE";
377 			break;
378 		}
379 
380 		case B_MESSENGER_TYPE:
381 		{
382 			field_type = "B_MESSENGER_TYPE";
383 			break;
384 		}
385 
386 		case B_POINT_TYPE:
387 		{
388 			field_type = "B_POINT_TYPE";
389 			field_data << "{ ";
390 			for (const BPoint* data_ptr = (const BPoint*)rawData;
391 				rawCount > 0;
392 				rawCount--, data_ptr++)
393 			{
394 				separator = (1 < rawCount) ? ", " : " }";
395 				field_data << "(" << data_ptr->x << ", " << data_ptr->y << ")" << separator;
396 			}
397 			break;
398 		}
399 
400 		case B_RECT_TYPE:
401 		{
402 			field_type = "B_RECT_TYPE";
403 			break;
404 		}
405 
406 //		case B_PATH_TYPE:					s = "B_PATH_TYPE";					break;
407 
408 		case B_REF_TYPE:
409 		{
410 			field_type = "B_REF_TYPE";
411 			break;
412 		}
413 
414 		case B_RGB_COLOR_TYPE:
415 		{
416 			field_type = "B_RGB_COLOR_TYPE";
417 			break;
418 		}
419 
420 		case B_PATTERN_TYPE:
421 		{
422 			field_type = "B_PATTERN_TYPE";
423 			break;
424 		}
425 
426 		case B_STRING_TYPE:
427 		{
428 			field_type = "B_STRING_TYPE";
429 			field_data << "{ ";
430 			for (const char* data_ptr = (const char*)rawData;
431 				rawCount > 0;
432 				rawCount--, data_ptr+= strlen(data_ptr) )
433 			{
434 				separator = (1 < rawCount) ? ", " : " }";
435 				field_data << "\"" << data_ptr << "\"" << separator;
436 			}
437 			break;
438 		}
439 
440 		case B_MONOCHROME_1_BIT_TYPE:
441 		{
442 			field_type = "B_MONOCHROME_1_BIT_TYPE";
443 			break;
444 		}
445 
446 		case B_GRAYSCALE_8_BIT_TYPE:
447 		{
448 			field_type = "B_GRAYSCALE_8_BIT_TYPE";
449 			break;
450 		}
451 
452 		case B_COLOR_8_BIT_TYPE:
453 		{
454 			field_type = "B_COLOR_8_BIT_TYPE";
455 			break;
456 		}
457 
458 		case B_RGB_32_BIT_TYPE:
459 		{
460 			field_type = "B_RGB_32_BIT_TYPE";
461 			break;
462 		}
463 
464 		case B_TIME_TYPE:
465 		{
466 			field_type = "B_TIME_TYPE";
467 			break;
468 		}
469 
470 		case B_MEDIA_PARAMETER_TYPE:
471 		{
472 			field_type = "B_MEDIA_PARAMETER_TYPE";
473 			break;
474 		}
475 
476 		case B_MEDIA_PARAMETER_WEB_TYPE:
477 		{
478 			field_type = "B_MEDIA_PARAMETER_WEB_TYPE";
479 			break;
480 		}
481 
482 		case B_MEDIA_PARAMETER_GROUP_TYPE:
483 		{
484 			field_type = "B_MEDIA_PARAMETER_GROUP_TYPE";
485 			break;
486 		}
487 
488 		case B_RAW_TYPE:
489 		{
490 			field_type = "B_RAW_TYPE";
491 			break;
492 		}
493 
494 		case B_MIME_TYPE:
495 		{
496 			field_type = "B_MIME_TYPE";
497 			break;
498 		}
499 
500 		case B_ANY_TYPE:
501 		{
502 			field_type = "B_ANY_TYPE";
503 			break;
504 		}
505 
506 		default:
507 		{
508 			field_type = "UNKNOWN_TYPE";
509 			break;
510 		}
511 	}
512 
513     sprintf(msg_buffer,
514             "    %-18s %-18s [%2d] = %s\n",
515             field_type,
516             fieldName,
517             field_count,
518             field_data.String() );
519 
520     m_outfile->Write(msg_buffer, strlen(msg_buffer) );
521 }
522