xref: /haiku/src/tests/servers/input/msgspy/MsgSpy.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
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 
120 		// Keyboard device event messages.
121 		case B_KEY_DOWN:					s = "B_KEY_DOWN";					break;
122 		case B_UNMAPPED_KEY_DOWN:			s = "B_UNMAPPED_KEY_DOWN";			break;
123 		case B_KEY_UP:						s = "B_KEY_UP";						break;
124 		case B_UNMAPPED_KEY_UP:				s = "B_UNMAPPED_KEY_UP";			break;
125 		case B_MODIFIERS_CHANGED:			s = "B_MODIFIERS_CHANGED";			break;
126 
127 		default:							s = "UNKNOWN_MESSAGE";				break;
128 	}
129 	return s;
130 }
131 
132 //-------------------------------------------------------------------------
133 //-------------------------------------------------------------------------
134 void MsgSpy::OutputMsgField(const char*  fieldName,
135                             const uint32 rawType,
136                             int          rawCount,
137                             const void*  rawData)
138 {
139 	char        msg_buffer   [1024];
140 	char        value_buffer [256];
141 	BString     field_data;
142     const char* field_type;
143     const int   field_count  = rawCount;
144     const char* separator;
145 
146 	switch (rawType)
147 	{
148 		case B_CHAR_TYPE:
149 		{
150 			field_type = "B_CHAR_TYPE";
151 			field_data << "{ ";
152 			for (const char* data_ptr = (const char*)rawData;
153 				rawCount > 0;
154 				rawCount--, data_ptr++)
155 			{
156 				separator = (1 < rawCount) ? ", " : " }";
157 				field_data << *data_ptr << separator;
158 			}
159 			break;
160 		}
161 
162 		case B_INT8_TYPE:
163 		{
164 			field_type = "B_INT8_TYPE";
165 			field_data << "{ ";
166 			for (const int8* data_ptr = (const int8*)rawData;
167 				rawCount > 0;
168 				rawCount--, data_ptr++)
169 			{
170 				separator = (1 < rawCount) ? ", " : " }";
171 				field_data << *data_ptr << separator;
172 			}
173 			break;
174 		}
175 
176 		case B_INT16_TYPE:
177 		{
178 			field_type = "B_INT16_TYPE";
179 			field_data << "{ ";
180 			for (const int16* data_ptr = (const int16*)rawData;
181 				rawCount > 0;
182 				rawCount--, data_ptr++)
183 			{
184 				separator = (1 < rawCount) ? ", " : " }";
185 				field_data << *data_ptr << separator;
186 			}
187 			break;
188 		}
189 
190 		case B_INT32_TYPE:
191 		{
192 			field_type = "B_INT32_TYPE";
193 			field_data << "{ ";
194 			for (const int32* data_ptr = (const int32*)rawData;
195 				rawCount > 0;
196 				rawCount--, data_ptr++)
197 			{
198 				separator = (1 < rawCount) ? ", " : " }";
199 				field_data << *data_ptr << separator;
200 			}
201 			break;
202 		}
203 
204 		case B_INT64_TYPE:
205 		{
206 			field_type = "B_INT64_TYPE";
207 			field_data << "{ ";
208 			for (const int64* data_ptr = (const int64*)rawData;
209 				rawCount > 0;
210 				rawCount--, data_ptr++)
211 			{
212 				separator = (1 < rawCount) ? ", " : " }";
213 				field_data << *data_ptr << separator;
214 			}
215 			break;
216 		}
217 
218 		case B_UINT8_TYPE:
219 		{
220 			field_type = "B_UINT8_TYPE";
221 			field_data << "{ ";
222 			for (const uint8* data_ptr = (const uint8*)rawData;
223 				rawCount > 0;
224 				rawCount--, data_ptr++)
225 			{
226 				separator = (1 < rawCount) ? ", " : " }";
227 				field_data << (uint32)(*data_ptr) << separator;
228 			}
229 			break;
230 		}
231 
232 		case B_UINT16_TYPE:
233 		{
234 			field_type = "B_UINT16_TYPE";
235 			field_data << "{ ";
236 			for (const uint16* data_ptr = (const uint16*)rawData;
237 				rawCount > 0;
238 				rawCount--, data_ptr++)
239 			{
240 				separator = (1 < rawCount) ? ", " : " }";
241 				field_data << (uint32)(*data_ptr) << separator;
242 			}
243 			break;
244 		}
245 
246 		case B_UINT32_TYPE:
247 		{
248 			field_type = "B_UINT32_TYPE";
249 			field_data << "{ ";
250 			for (const uint32* data_ptr = (const uint32*)rawData;
251 				rawCount > 0;
252 				rawCount--, data_ptr++)
253 			{
254 				separator = (1 < rawCount) ? ", " : " }";
255 				field_data << *data_ptr << separator;
256 			}
257 			break;
258 		}
259 
260 		case B_UINT64_TYPE:
261 		{
262 			field_type = "B_UINT64_TYPE";
263 			field_data << "{ ";
264 			for (const uint64* data_ptr = (const uint64*)rawData;
265 				rawCount > 0;
266 				rawCount--, data_ptr++)
267 			{
268 				separator = (1 < rawCount) ? ", " : " }";
269 				field_data << *data_ptr << separator;
270 			}
271 			break;
272 		}
273 
274 		case B_FLOAT_TYPE:
275 		{
276 			field_type = "B_FLOAT_TYPE";
277 			field_data << "{ ";
278 			for (const float* data_ptr = (const float*)rawData;
279 				rawCount > 0;
280 				rawCount--, data_ptr++)
281 			{
282 				separator = (1 < rawCount) ? ", " : " }";
283 				field_data << *data_ptr << separator;
284 			}
285 			break;
286 		}
287 
288 		case B_DOUBLE_TYPE:
289 		{
290 			field_type = "B_DOUBLE_TYPE";
291 			field_data << "{ ";
292 			for (const double* data_ptr = (const double*)rawData;
293 				rawCount > 0;
294 				rawCount--, data_ptr++)
295 			{
296 				separator = (1 < rawCount) ? ", " : " }";
297 				sprintf(value_buffer, "%f", *data_ptr);
298 				field_data << value_buffer << separator;
299 			}
300 			break;
301 		}
302 
303 		case B_BOOL_TYPE:
304 		{
305 			field_type = "B_BOOL_TYPE";
306 			field_data << "{ ";
307 			for (const bool* data_ptr = (const bool*)rawData;
308 				rawCount > 0;
309 				rawCount--, data_ptr++)
310 			{
311 				separator = (1 < rawCount) ? ", " : " }";
312 				sprintf(value_buffer, "%s", (true == *data_ptr) ? "true" : "false");
313 				field_data << value_buffer << separator;
314 			}
315 			break;
316 		}
317 
318 		case B_OFF_T_TYPE:
319 		{
320 			field_type = "B_OFF_T_TYPE";
321 			field_data << "{ ";
322 			for (const off_t* data_ptr = (const off_t*)rawData;
323 				rawCount > 0;
324 				rawCount--, data_ptr++)
325 			{
326 				separator = (1 < rawCount) ? ", " : " }";
327 				field_data << *data_ptr << separator;
328 			}
329 			break;
330 		}
331 
332 		case B_SIZE_T_TYPE:
333 		{
334 			field_type = "B_SIZE_T_TYPE";
335 			field_data << "{ ";
336 			for (const size_t* data_ptr = (const size_t*)rawData;
337 				rawCount > 0;
338 				rawCount--, data_ptr++)
339 			{
340 				separator = (1 < rawCount) ? ", " : " }";
341 				field_data << *data_ptr << separator;
342 			}
343 			break;
344 		}
345 
346 		case B_SSIZE_T_TYPE:
347 		{
348 			field_type = "B_SSIZE_T_TYPE";
349 			field_data << "{ ";
350 			for (const ssize_t* data_ptr = (const ssize_t*)rawData;
351 				rawCount > 0;
352 				rawCount--, data_ptr++)
353 			{
354 				separator = (1 < rawCount) ? ", " : " }";
355 				field_data << *data_ptr << separator;
356 			}
357 			break;
358 		}
359 
360 		case B_POINTER_TYPE:
361 		{
362 			field_type = "B_POINTER_TYPE";
363 			break;
364 		}
365 
366 		case B_OBJECT_TYPE:
367 		{
368 			field_type = "B_OBJECT_TYPE";
369 			break;
370 		}
371 
372 		case B_MESSAGE_TYPE:
373 		{
374 			field_type = "B_MESSAGE_TYPE";
375 			break;
376 		}
377 
378 		case B_MESSENGER_TYPE:
379 		{
380 			field_type = "B_MESSENGER_TYPE";
381 			break;
382 		}
383 
384 		case B_POINT_TYPE:
385 		{
386 			field_type = "B_POINT_TYPE";
387 			field_data << "{ ";
388 			for (const BPoint* data_ptr = (const BPoint*)rawData;
389 				rawCount > 0;
390 				rawCount--, data_ptr++)
391 			{
392 				separator = (1 < rawCount) ? ", " : " }";
393 				field_data << "(" << data_ptr->x << ", " << data_ptr->y << ")" << separator;
394 			}
395 			break;
396 		}
397 
398 		case B_RECT_TYPE:
399 		{
400 			field_type = "B_RECT_TYPE";
401 			break;
402 		}
403 
404 //		case B_PATH_TYPE:					s = "B_PATH_TYPE";					break;
405 
406 		case B_REF_TYPE:
407 		{
408 			field_type = "B_REF_TYPE";
409 			break;
410 		}
411 
412 		case B_RGB_COLOR_TYPE:
413 		{
414 			field_type = "B_RGB_COLOR_TYPE";
415 			break;
416 		}
417 
418 		case B_PATTERN_TYPE:
419 		{
420 			field_type = "B_PATTERN_TYPE";
421 			break;
422 		}
423 
424 		case B_STRING_TYPE:
425 		{
426 			field_type = "B_STRING_TYPE";
427 			field_data << "{ ";
428 			for (const char* data_ptr = (const char*)rawData;
429 				rawCount > 0;
430 				rawCount--, data_ptr+= strlen(data_ptr) )
431 			{
432 				separator = (1 < rawCount) ? ", " : " }";
433 				field_data << "\"" << data_ptr << "\"" << separator;
434 			}
435 			break;
436 		}
437 
438 		case B_MONOCHROME_1_BIT_TYPE:
439 		{
440 			field_type = "B_MONOCHROME_1_BIT_TYPE";
441 			break;
442 		}
443 
444 		case B_GRAYSCALE_8_BIT_TYPE:
445 		{
446 			field_type = "B_GRAYSCALE_8_BIT_TYPE";
447 			break;
448 		}
449 
450 		case B_COLOR_8_BIT_TYPE:
451 		{
452 			field_type = "B_COLOR_8_BIT_TYPE";
453 			break;
454 		}
455 
456 		case B_RGB_32_BIT_TYPE:
457 		{
458 			field_type = "B_RGB_32_BIT_TYPE";
459 			break;
460 		}
461 
462 		case B_TIME_TYPE:
463 		{
464 			field_type = "B_TIME_TYPE";
465 			break;
466 		}
467 
468 		case B_MEDIA_PARAMETER_TYPE:
469 		{
470 			field_type = "B_MEDIA_PARAMETER_TYPE";
471 			break;
472 		}
473 
474 		case B_MEDIA_PARAMETER_WEB_TYPE:
475 		{
476 			field_type = "B_MEDIA_PARAMETER_WEB_TYPE";
477 			break;
478 		}
479 
480 		case B_MEDIA_PARAMETER_GROUP_TYPE:
481 		{
482 			field_type = "B_MEDIA_PARAMETER_GROUP_TYPE";
483 			break;
484 		}
485 
486 		case B_RAW_TYPE:
487 		{
488 			field_type = "B_RAW_TYPE";
489 			break;
490 		}
491 
492 		case B_MIME_TYPE:
493 		{
494 			field_type = "B_MIME_TYPE";
495 			break;
496 		}
497 
498 		case B_ANY_TYPE:
499 		{
500 			field_type = "B_ANY_TYPE";
501 			break;
502 		}
503 
504 		default:
505 		{
506 			field_type = "UNKNOWN_TYPE";
507 			break;
508 		}
509 	}
510 
511     sprintf(msg_buffer,
512             "    %-18s %-18s [%2d] = %s\n",
513             field_type,
514             fieldName,
515             field_count,
516             field_data.String() );
517 
518     m_outfile->Write(msg_buffer, strlen(msg_buffer) );
519 }
520