00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "winStatsMonitor.h"
00016 #include "winStatsServer.h"
00017 #include "winStatsStripChart.h"
00018 #include "winStatsPianoRoll.h"
00019 #include "winStatsChartMenu.h"
00020 #include "winStatsMenuId.h"
00021 #include "pStatGraph.h"
00022 #include "pStatCollectorDef.h"
00023 #include "indent.h"
00024
00025 bool WinStatsMonitor::_window_class_registered = false;
00026 const char * const WinStatsMonitor::_window_class_name = "monitor";
00027
00028
00029
00030
00031
00032
00033 WinStatsMonitor::
00034 WinStatsMonitor(WinStatsServer *server) : PStatMonitor(server) {
00035 _window = 0;
00036 _menu_bar = 0;
00037 _options_menu = 0;
00038
00039
00040 _time_units = 0;
00041 _scroll_speed = 0.0;
00042 _pause = false;
00043 }
00044
00045
00046
00047
00048
00049
00050 WinStatsMonitor::
00051 ~WinStatsMonitor() {
00052 Graphs::iterator gi;
00053 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00054 delete (*gi);
00055 }
00056 _graphs.clear();
00057
00058 ChartMenus::iterator mi;
00059 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
00060 delete (*mi);
00061 }
00062 _chart_menus.clear();
00063
00064 if (_window) {
00065 DestroyWindow(_window);
00066 _window = 0;
00067 }
00068
00069 #ifdef DEVELOP_WINSTATS
00070
00071 exit(0);
00072 #endif
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 string WinStatsMonitor::
00082 get_monitor_name() {
00083 return "WinStats";
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 void WinStatsMonitor::
00098 initialized() {
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108 void WinStatsMonitor::
00109 got_hello() {
00110 create_window();
00111 open_strip_chart(0, 0, false);
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 void WinStatsMonitor::
00126 got_bad_version(int client_major, int client_minor,
00127 int server_major, int server_minor) {
00128 ostringstream str;
00129 str << "Unable to honor connection attempt from "
00130 << get_client_progname() << " on " << get_client_hostname()
00131 << ": unsupported PStats version "
00132 << client_major << "." << client_minor;
00133
00134 if (server_minor == 0) {
00135 str << " (server understands version " << server_major
00136 << "." << server_minor << " only).";
00137 } else {
00138 str << " (server understands versions " << server_major
00139 << ".0 through " << server_major << "." << server_minor << ").";
00140 }
00141
00142 string message = str.str();
00143 MessageBox(NULL, message.c_str(), "Bad version",
00144 MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 void WinStatsMonitor::
00159 new_collector(int collector_index) {
00160 Graphs::iterator gi;
00161 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00162 WinStatsGraph *graph = (*gi);
00163 graph->new_collector(collector_index);
00164 }
00165
00166
00167 ChartMenus::iterator mi;
00168 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
00169 (*mi)->do_update();
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 void WinStatsMonitor::
00185 new_thread(int thread_index) {
00186 WinStatsChartMenu *chart_menu = new WinStatsChartMenu(this, thread_index);
00187 chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
00188 _chart_menus.push_back(chart_menu);
00189 DrawMenuBar(_window);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 void WinStatsMonitor::
00202 new_data(int thread_index, int frame_number) {
00203 Graphs::iterator gi;
00204 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00205 WinStatsGraph *graph = (*gi);
00206 graph->new_data(thread_index, frame_number);
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 void WinStatsMonitor::
00220 lost_connection() {
00221 nout << "Lost connection to " << get_client_hostname() << "\n";
00222
00223 if (_window) {
00224 DestroyWindow(_window);
00225 _window = 0;
00226 }
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 void WinStatsMonitor::
00237 idle() {
00238
00239 ChartMenus::iterator mi;
00240 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
00241 (*mi)->check_update();
00242 }
00243
00244
00245 const PStatThreadData *thread_data = get_client_data()->get_thread_data(0);
00246 double frame_rate = thread_data->get_frame_rate();
00247 if (frame_rate != 0.0f) {
00248 char buffer[128];
00249 sprintf(buffer, "%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate);
00250
00251 MENUITEMINFO mii;
00252 memset(&mii, 0, sizeof(mii));
00253 mii.cbSize = sizeof(mii);
00254 mii.fMask = MIIM_STRING;
00255 mii.dwTypeData = buffer;
00256 SetMenuItemInfo(_menu_bar, MI_frame_rate_label, FALSE, &mii);
00257 DrawMenuBar(_window);
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 bool WinStatsMonitor::
00268 has_idle() {
00269 return true;
00270 }
00271
00272
00273
00274
00275
00276
00277 void WinStatsMonitor::
00278 user_guide_bars_changed() {
00279 Graphs::iterator gi;
00280 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00281 WinStatsGraph *graph = (*gi);
00282 graph->user_guide_bars_changed();
00283 }
00284 }
00285
00286
00287
00288
00289
00290
00291 HWND WinStatsMonitor::
00292 get_window() const {
00293 return _window;
00294 }
00295
00296
00297
00298
00299
00300
00301 void WinStatsMonitor::
00302 open_strip_chart(int thread_index, int collector_index, bool show_level) {
00303 WinStatsStripChart *graph =
00304 new WinStatsStripChart(this, thread_index, collector_index, show_level);
00305 add_graph(graph);
00306
00307 graph->set_time_units(_time_units);
00308 graph->set_scroll_speed(_scroll_speed);
00309 graph->set_pause(_pause);
00310 }
00311
00312
00313
00314
00315
00316
00317 void WinStatsMonitor::
00318 open_piano_roll(int thread_index) {
00319 WinStatsPianoRoll *graph = new WinStatsPianoRoll(this, thread_index);
00320 add_graph(graph);
00321
00322 graph->set_time_units(_time_units);
00323 graph->set_scroll_speed(_scroll_speed);
00324 graph->set_pause(_pause);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334 const WinStatsMonitor::MenuDef &WinStatsMonitor::
00335 lookup_menu(int menu_id) const {
00336 static MenuDef invalid(0, 0, false);
00337 int menu_index = menu_id - MI_new_chart;
00338 nassertr(menu_index >= 0 && menu_index < (int)_menu_by_id.size(), invalid);
00339 return _menu_by_id[menu_index];
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 int WinStatsMonitor::
00352 get_menu_id(const MenuDef &menu_def) {
00353 MenuByDef::iterator mi;
00354 mi = _menu_by_def.find(menu_def);
00355 if (mi != _menu_by_def.end()) {
00356 return (*mi).second;
00357 }
00358
00359
00360 int menu_id = (int)_menu_by_id.size() + MI_new_chart;
00361 _menu_by_id.push_back(menu_def);
00362 _menu_by_def[menu_def] = menu_id;
00363
00364 return menu_id;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 void WinStatsMonitor::
00376 set_time_units(int unit_mask) {
00377 _time_units = unit_mask;
00378
00379
00380 Graphs::iterator gi;
00381 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00382 WinStatsGraph *graph = (*gi);
00383 graph->set_time_units(_time_units);
00384 }
00385
00386
00387 MENUITEMINFO mii;
00388 memset(&mii, 0, sizeof(mii));
00389 mii.cbSize = sizeof(mii);
00390 mii.fMask = MIIM_STATE;
00391
00392 mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ?
00393 MFS_CHECKED : MFS_UNCHECKED;
00394 SetMenuItemInfo(_options_menu, MI_time_ms, FALSE, &mii);
00395
00396 mii.fState = ((_time_units & PStatGraph::GBU_hz) != 0) ?
00397 MFS_CHECKED : MFS_UNCHECKED;
00398 SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii);
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 void WinStatsMonitor::
00409 set_scroll_speed(double scroll_speed) {
00410 _scroll_speed = scroll_speed;
00411
00412
00413 Graphs::iterator gi;
00414 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00415 WinStatsGraph *graph = (*gi);
00416 graph->set_scroll_speed(_scroll_speed);
00417 }
00418
00419
00420 MENUITEMINFO mii;
00421 memset(&mii, 0, sizeof(mii));
00422 mii.cbSize = sizeof(mii);
00423 mii.fMask = MIIM_STATE;
00424
00425 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 1.0, 0.1) ?
00426 MFS_CHECKED : MFS_UNCHECKED;
00427 SetMenuItemInfo(_speed_menu, MI_speed_1, FALSE, &mii);
00428
00429 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 2.0, 0.1) ?
00430 MFS_CHECKED : MFS_UNCHECKED;
00431 SetMenuItemInfo(_speed_menu, MI_speed_2, FALSE, &mii);
00432
00433 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 3.0, 0.1) ?
00434 MFS_CHECKED : MFS_UNCHECKED;
00435 SetMenuItemInfo(_speed_menu, MI_speed_3, FALSE, &mii);
00436
00437 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 6.0, 0.1) ?
00438 MFS_CHECKED : MFS_UNCHECKED;
00439 SetMenuItemInfo(_speed_menu, MI_speed_6, FALSE, &mii);
00440
00441 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 12.0, 0.1) ?
00442 MFS_CHECKED : MFS_UNCHECKED;
00443 SetMenuItemInfo(_speed_menu, MI_speed_12, FALSE, &mii);
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 void WinStatsMonitor::
00453 set_pause(bool pause) {
00454 _pause = pause;
00455
00456
00457 Graphs::iterator gi;
00458 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
00459 WinStatsGraph *graph = (*gi);
00460 graph->set_pause(_pause);
00461 }
00462
00463
00464 MENUITEMINFO mii;
00465 memset(&mii, 0, sizeof(mii));
00466 mii.cbSize = sizeof(mii);
00467 mii.fMask = MIIM_STATE;
00468
00469 mii.fState = _pause ? MFS_CHECKED : MFS_UNCHECKED;
00470 SetMenuItemInfo(_speed_menu, MI_pause, FALSE, &mii);
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 void WinStatsMonitor::
00480 add_graph(WinStatsGraph *graph) {
00481 _graphs.insert(graph);
00482 }
00483
00484
00485
00486
00487
00488
00489 void WinStatsMonitor::
00490 remove_graph(WinStatsGraph *graph) {
00491 Graphs::iterator gi = _graphs.find(graph);
00492 if (gi != _graphs.end()) {
00493 _graphs.erase(gi);
00494 delete graph;
00495 }
00496 }
00497
00498
00499
00500
00501
00502
00503 void WinStatsMonitor::
00504 create_window() {
00505 if (_window) {
00506 return;
00507 }
00508
00509 HINSTANCE application = GetModuleHandle(NULL);
00510 register_window_class(application);
00511
00512 _menu_bar = CreateMenu();
00513
00514 setup_options_menu();
00515 setup_speed_menu();
00516 setup_frame_rate_label();
00517
00518 ChartMenus::iterator mi;
00519 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
00520 (*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
00521 }
00522
00523 _window_title = get_client_progname() + " on " + get_client_hostname();
00524 DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
00525 WS_CLIPSIBLINGS | WS_VISIBLE;
00526
00527 _window =
00528 CreateWindow(_window_class_name, _window_title.c_str(), window_style,
00529 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
00530 NULL, _menu_bar, application, 0);
00531 if (!_window) {
00532 nout << "Could not create monitor window!\n";
00533 exit(1);
00534 }
00535
00536 SetWindowLongPtr(_window, 0, (LONG_PTR)this);
00537
00538
00539
00540 ShowWindow(_window, SW_RESTORE);
00541 SetForegroundWindow(_window);
00542 }
00543
00544
00545
00546
00547
00548
00549 void WinStatsMonitor::
00550 setup_options_menu() {
00551 _options_menu = CreatePopupMenu();
00552
00553 MENUITEMINFO mii;
00554 memset(&mii, 0, sizeof(mii));
00555 mii.cbSize = sizeof(mii);
00556
00557 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
00558 mii.fType = MFT_STRING;
00559 mii.hSubMenu = _options_menu;
00560
00561
00562
00563
00564
00565 mii.dwTypeData = "Units";
00566 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
00567
00568
00569 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
00570 mii.fType = MFT_STRING | MFT_RADIOCHECK;
00571 mii.hbmpChecked = NULL;
00572 mii.hbmpUnchecked = NULL;
00573 mii.fState = MFS_UNCHECKED;
00574 mii.wID = MI_time_ms;
00575 mii.dwTypeData = "ms";
00576 InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
00577
00578 mii.wID = MI_time_hz;
00579 mii.dwTypeData = "Hz";
00580 InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
00581
00582 set_time_units(PStatGraph::GBU_ms);
00583 }
00584
00585
00586
00587
00588
00589
00590 void WinStatsMonitor::
00591 setup_speed_menu() {
00592 _speed_menu = CreatePopupMenu();
00593
00594 MENUITEMINFO mii;
00595 memset(&mii, 0, sizeof(mii));
00596 mii.cbSize = sizeof(mii);
00597
00598 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
00599 mii.fType = MFT_STRING;
00600 mii.hSubMenu = _speed_menu;
00601 mii.dwTypeData = "Speed";
00602 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
00603
00604
00605 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
00606 mii.fType = MFT_STRING | MFT_RADIOCHECK;
00607 mii.hbmpChecked = NULL;
00608 mii.hbmpUnchecked = NULL;
00609 mii.fState = MFS_UNCHECKED;
00610 mii.wID = MI_speed_1;
00611 mii.dwTypeData = "1";
00612 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00613
00614 mii.wID = MI_speed_2;
00615 mii.dwTypeData = "2";
00616 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00617
00618 mii.wID = MI_speed_3;
00619 mii.dwTypeData = "3";
00620 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00621
00622 mii.wID = MI_speed_6;
00623 mii.dwTypeData = "6";
00624 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00625
00626 mii.wID = MI_speed_12;
00627 mii.dwTypeData = "12";
00628 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00629
00630 mii.fMask = MIIM_FTYPE;
00631 mii.fType = MFT_SEPARATOR;
00632 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00633
00634 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
00635 mii.fType = MFT_STRING;
00636 mii.wID = MI_pause;
00637 mii.dwTypeData = "pause";
00638 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
00639
00640 set_scroll_speed(3);
00641 set_pause(false);
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 void WinStatsMonitor::
00654 setup_frame_rate_label() {
00655 MENUITEMINFO mii;
00656 memset(&mii, 0, sizeof(mii));
00657 mii.cbSize = sizeof(mii);
00658
00659 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
00660 mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY;
00661 mii.wID = MI_frame_rate_label;
00662 mii.dwTypeData = "";
00663 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
00664 }
00665
00666
00667
00668
00669
00670
00671
00672 void WinStatsMonitor::
00673 register_window_class(HINSTANCE application) {
00674 if (_window_class_registered) {
00675 return;
00676 }
00677
00678 WNDCLASS wc;
00679
00680 ZeroMemory(&wc, sizeof(WNDCLASS));
00681 wc.style = 0;
00682 wc.lpfnWndProc = (WNDPROC)static_window_proc;
00683 wc.hInstance = application;
00684 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00685 wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
00686 wc.lpszMenuName = NULL;
00687 wc.lpszClassName = _window_class_name;
00688
00689
00690 wc.cbWndExtra = sizeof(WinStatsMonitor *);
00691
00692 if (!RegisterClass(&wc)) {
00693 nout << "Could not register monitor window class!\n";
00694 exit(1);
00695 }
00696
00697 _window_class_registered = true;
00698 }
00699
00700
00701
00702
00703
00704
00705 LONG WINAPI WinStatsMonitor::
00706 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00707 WinStatsMonitor *self = (WinStatsMonitor *)GetWindowLongPtr(hwnd, 0);
00708 if (self != (WinStatsMonitor *)NULL && self->_window == hwnd) {
00709 return self->window_proc(hwnd, msg, wparam, lparam);
00710 } else {
00711 return DefWindowProc(hwnd, msg, wparam, lparam);
00712 }
00713 }
00714
00715
00716
00717
00718
00719
00720 LONG WinStatsMonitor::
00721 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00722 switch (msg) {
00723 case WM_DESTROY:
00724 close();
00725 break;
00726
00727 case WM_COMMAND:
00728 if (HIWORD(wparam) <= 1) {
00729 int menu_id = LOWORD(wparam);
00730 handle_menu_command(menu_id);
00731 return 0;
00732 }
00733 break;
00734
00735 default:
00736 break;
00737 }
00738
00739 return DefWindowProc(hwnd, msg, wparam, lparam);
00740 }
00741
00742
00743
00744
00745
00746
00747 void WinStatsMonitor::
00748 handle_menu_command(int menu_id) {
00749 switch (menu_id) {
00750 case MI_none:
00751 break;
00752
00753 case MI_time_ms:
00754 set_time_units(PStatGraph::GBU_ms);
00755 break;
00756
00757 case MI_time_hz:
00758 set_time_units(PStatGraph::GBU_hz);
00759 break;
00760
00761 case MI_speed_1:
00762 set_scroll_speed(1);
00763 break;
00764
00765 case MI_speed_2:
00766 set_scroll_speed(2);
00767 break;
00768
00769 case MI_speed_3:
00770 set_scroll_speed(3);
00771 break;
00772
00773 case MI_speed_6:
00774 set_scroll_speed(6);
00775 break;
00776
00777 case MI_speed_12:
00778 set_scroll_speed(12);
00779 break;
00780
00781 case MI_pause:
00782 set_pause(!_pause);
00783 break;
00784
00785 default:
00786 if (menu_id >= MI_new_chart) {
00787 const MenuDef &menu_def = lookup_menu(menu_id);
00788 if (menu_def._collector_index < 0) {
00789 open_piano_roll(menu_def._thread_index);
00790 } else {
00791 open_strip_chart(menu_def._thread_index, menu_def._collector_index,
00792 menu_def._show_level);
00793 }
00794 }
00795 }
00796 }