* The beginnings of an activity monitor application. Very bare and feature-less
right now, but it's already working (and shows that we better compute our system_info::cached_pages field directly). * I am not sure if we want to keep this app here, merge it with ProcessController, or have it as a separate (3rdparty) app. Opinions welcome. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24846 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,6 +2,7 @@ SubDir HAIKU_TOP src apps ;
|
|||||||
|
|
||||||
SubInclude HAIKU_TOP src apps 3dmov ;
|
SubInclude HAIKU_TOP src apps 3dmov ;
|
||||||
SubInclude HAIKU_TOP src apps aboutsystem ;
|
SubInclude HAIKU_TOP src apps aboutsystem ;
|
||||||
|
SubInclude HAIKU_TOP src apps activitymonitor ;
|
||||||
SubInclude HAIKU_TOP src apps bsnow ;
|
SubInclude HAIKU_TOP src apps bsnow ;
|
||||||
SubInclude HAIKU_TOP src apps bootman ;
|
SubInclude HAIKU_TOP src apps bootman ;
|
||||||
SubInclude HAIKU_TOP src apps cdplayer ;
|
SubInclude HAIKU_TOP src apps cdplayer ;
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ActivityMonitor.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <TextView.h>
|
||||||
|
|
||||||
|
#include "ActivityWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char* kSignature = "application/x-vnd.Haiku-ActivityMonitor";
|
||||||
|
|
||||||
|
|
||||||
|
ActivityMonitor::ActivityMonitor()
|
||||||
|
: BApplication(kSignature)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ActivityMonitor::~ActivityMonitor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityMonitor::ReadyToRun()
|
||||||
|
{
|
||||||
|
fWindow = new ActivityWindow();
|
||||||
|
fWindow->Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityMonitor::RefsReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
fWindow->PostMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityMonitor::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
BApplication::MessageReceived(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityMonitor::AboutRequested()
|
||||||
|
{
|
||||||
|
ShowAbout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
ActivityMonitor::ShowAbout()
|
||||||
|
{
|
||||||
|
BAlert *alert = new BAlert("about", "ActivityMonitor\n"
|
||||||
|
"\twritten by Axel Dörfler\n"
|
||||||
|
"\tCopyright 2008, Haiku Inc.\n", "Ok");
|
||||||
|
BTextView *view = alert->TextView();
|
||||||
|
BFont font;
|
||||||
|
|
||||||
|
view->SetStylable(true);
|
||||||
|
|
||||||
|
view->GetFont(&font);
|
||||||
|
font.SetSize(18);
|
||||||
|
font.SetFace(B_BOLD_FACE);
|
||||||
|
view->SetFontAndColor(0, 15, &font);
|
||||||
|
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int /*argc*/, char** /*argv*/)
|
||||||
|
{
|
||||||
|
ActivityMonitor app;
|
||||||
|
app.Run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ACTIVITY_MONITOR_H
|
||||||
|
#define ACTIVITY_MONITOR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
class ActivityWindow;
|
||||||
|
|
||||||
|
|
||||||
|
class ActivityMonitor : public BApplication {
|
||||||
|
public:
|
||||||
|
ActivityMonitor();
|
||||||
|
virtual ~ActivityMonitor();
|
||||||
|
|
||||||
|
virtual void ReadyToRun();
|
||||||
|
|
||||||
|
virtual void RefsReceived(BMessage* message);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
virtual void AboutRequested();
|
||||||
|
|
||||||
|
static void ShowAbout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActivityWindow* fWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const char* kSignature;
|
||||||
|
|
||||||
|
#endif // ACTIVITY_MONITOR_H
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku-ActivityMonitor";
|
||||||
|
|
||||||
|
resource app_version {
|
||||||
|
major = 1,
|
||||||
|
middle = 0,
|
||||||
|
minor = 0,
|
||||||
|
|
||||||
|
variety = B_APPV_BETA,
|
||||||
|
internal = 3,
|
||||||
|
|
||||||
|
short_info = "ActivityMonitor",
|
||||||
|
long_info = "ActivityMonitor ©2008 Haiku, Inc."
|
||||||
|
};
|
||||||
|
|
||||||
|
resource app_flags B_MULTIPLE_LAUNCH;
|
||||||
|
|
||||||
|
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
|
|
||||||
|
resource vector_icon {
|
||||||
|
$"6E6369660E03010000020002023980000000000000004000004BE00008908100"
|
||||||
|
$"010000FFFF01000000020016023CC7EE389BC0BA16573E39B04977C842ADC700"
|
||||||
|
$"FFFFD3020006023C529D3753A2B8966F3D9D084B6044496AAF00474747FFA5A0"
|
||||||
|
$"A002001602BC4E76BC411B3C90DABCA00D47587D4ABA850090FFD40200160238"
|
||||||
|
$"313C3B5CF0BFCD963C7AAC4C13943FCAF901ECFFC3054B04017E020006033E2F"
|
||||||
|
$"99387F17BA42DB3FF5B94A0E32482C90001D1E2C3D454658FF01010102000602"
|
||||||
|
$"3879063B8224BE2CC83B10DB4A1F6F49B894FF9A9A9A00242222020006033C69"
|
||||||
|
$"A60000000000003E186148800049800058F3F3F300D4CECEFFD9D9D902000603"
|
||||||
|
$"3C1F1A33E78CB7ACC03FFE4F48BB3EBD7B6C0078D905818CFF05FF7ADD050200"
|
||||||
|
$"1602349C2E37B5FABA1F6036FC624A3E004B320001D3FF910200160235777837"
|
||||||
|
$"0A67B7E8CE363A844A1D684B45D800F3FF2E0D0A04486050605C51544E04033E"
|
||||||
|
$"5349594856475C49604B5C4E604B0A06262A264C485E5252523030240A04262A"
|
||||||
|
$"4838523030240A044838485E525252300A04262A264C485E48380A04453A4553"
|
||||||
|
$"2844282E0A04B6F9C0F42845282EB701B8EC0A044550455328452AC0F30A0445"
|
||||||
|
$"3A45502A43B701B8EC0408AEBAB6BCBCC32FBD4F2E3930BDA8B9ACC0A5BA9EBC"
|
||||||
|
$"03BB1EBFD937BF0DBD4FC072BCC3C019BDDBC0CB46460204BF23C726BF91C70D"
|
||||||
|
$"BEB5C73FBE9FC87EBE7AC7D9BEC5C922BFAAC97BBF3CC994C018C962C02DC823"
|
||||||
|
$"C053C8C8C008C77F0204BFCEC6FBC042C6E0BF5BC715BF48C85ABF1FC7B3BF71"
|
||||||
|
$"C902C063C95ABFF0C974C0D7C93FC0EAC7FAC113C8A2C0C1C7530E0A07010000"
|
||||||
|
$"0A0101011001178300040A0001021001178400040A020103000A080109000A0B"
|
||||||
|
$"010A1001178120040A030104000A04020506000A090107000A0A0108000A0D01"
|
||||||
|
$"0C0815FF0A0C010B0815FF0A0D010C0A3FEAF70000000000003FEAF7C573B4C2"
|
||||||
|
$"770615FF0A0C010B0A3FEAF70000000000003FEAF7C573B4C2770615FF"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
@@ -0,0 +1,500 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ActivityView.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <Dragger.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "ActivityMonitor.h"
|
||||||
|
#include "DataSource.h"
|
||||||
|
#include "SystemInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct data_item {
|
||||||
|
bigtime_t time;
|
||||||
|
int64 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bigtime_t kInitialRefreshInterval = 500000LL;
|
||||||
|
|
||||||
|
const uint32 kMsgRefresh = 'refr';
|
||||||
|
const uint32 kMsgToggleDataSource = 'tgds';
|
||||||
|
|
||||||
|
extern const char* kSignature;
|
||||||
|
|
||||||
|
|
||||||
|
DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval)
|
||||||
|
:
|
||||||
|
fBuffer(10000),
|
||||||
|
fMinimumValue(0),
|
||||||
|
fMaximumValue(0),
|
||||||
|
fRefreshInterval(interval),
|
||||||
|
fLastIndex(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataHistory::~DataHistory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DataHistory::AddValue(bigtime_t time, int64 value)
|
||||||
|
{
|
||||||
|
if (fBuffer.IsEmpty() || fMaximumValue < value)
|
||||||
|
fMaximumValue = value;
|
||||||
|
if (fBuffer.IsEmpty() || fMinimumValue > value)
|
||||||
|
fMinimumValue = value;
|
||||||
|
|
||||||
|
data_item item = {time, value};
|
||||||
|
fBuffer.AddItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
DataHistory::ValueAt(bigtime_t time)
|
||||||
|
{
|
||||||
|
// TODO: if the refresh rate changes, this computation won't work anymore!
|
||||||
|
int32 index = (time - Start()) / fRefreshInterval;
|
||||||
|
data_item* item = fBuffer.ItemAt(index);
|
||||||
|
if (item != NULL)
|
||||||
|
return item->value;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
DataHistory::MaximumValue() const
|
||||||
|
{
|
||||||
|
return fMaximumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
DataHistory::MinimumValue() const
|
||||||
|
{
|
||||||
|
return fMinimumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
DataHistory::Start() const
|
||||||
|
{
|
||||||
|
if (fBuffer.CountItems() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return fBuffer.ItemAt(0)->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
DataHistory::End() const
|
||||||
|
{
|
||||||
|
if (fBuffer.CountItems() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return fBuffer.ItemAt(fBuffer.CountItems() - 1)->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DataHistory::SetRefreshInterval(bigtime_t interval)
|
||||||
|
{
|
||||||
|
// TODO: adjust buffer size
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
ActivityView::ActivityView(BRect frame, const char* name,
|
||||||
|
const BMessage& settings, uint32 resizingMode)
|
||||||
|
: BView(frame, name, resizingMode,
|
||||||
|
B_WILL_DRAW | B_SUBPIXEL_PRECISE | B_FULL_UPDATE_ON_RESIZE
|
||||||
|
| B_FRAME_EVENTS)
|
||||||
|
{
|
||||||
|
_Init(&settings);
|
||||||
|
|
||||||
|
BRect rect(Bounds());
|
||||||
|
rect.top = rect.bottom - 7;
|
||||||
|
rect.left = rect.right - 7;
|
||||||
|
BDragger* dragger = new BDragger(rect, this,
|
||||||
|
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||||
|
AddChild(dragger);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ActivityView::ActivityView(BMessage* archive)
|
||||||
|
: BView(archive)
|
||||||
|
{
|
||||||
|
_Init(archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ActivityView::~ActivityView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::_Init(const BMessage* settings)
|
||||||
|
{
|
||||||
|
fBackgroundColor = (rgb_color){255, 255, 240};
|
||||||
|
SetLowColor(fBackgroundColor);
|
||||||
|
|
||||||
|
fRefreshInterval = kInitialRefreshInterval;
|
||||||
|
fDrawInterval = kInitialRefreshInterval * 2;
|
||||||
|
fLastRefresh = 0;
|
||||||
|
fDrawResolution = 1;
|
||||||
|
|
||||||
|
AddDataSource(new UsedMemoryDataSource());
|
||||||
|
AddDataSource(new CachedMemoryDataSource());
|
||||||
|
AddDataSource(new ThreadsDataSource());
|
||||||
|
AddDataSource(new CpuUsageDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityView::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
status = BView::Archive(into, deep);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = into->AddString("add_on", kSignature);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = SaveState(*into);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable*
|
||||||
|
ActivityView::Instantiate(BMessage* archive)
|
||||||
|
{
|
||||||
|
if (!validate_instantiation(archive, "ActivityView"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return new ActivityView(archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityView::SaveState(BMessage& state) const
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
ActivityView::FindDataSource(const char* name)
|
||||||
|
{
|
||||||
|
for (int32 i = fSources.CountItems(); i-- > 0;) {
|
||||||
|
DataSource* source = fSources.ItemAt(i);
|
||||||
|
if (!strcmp(source->Label(), name))
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityView::AddDataSource(DataSource* source)
|
||||||
|
{
|
||||||
|
DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
|
||||||
|
fRefreshInterval);
|
||||||
|
if (values == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!fValues.AddItem(values)) {
|
||||||
|
delete values;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fSources.AddItem(source)) {
|
||||||
|
fValues.RemoveItem(values);
|
||||||
|
delete values;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityView::RemoveDataSource(DataSource* source)
|
||||||
|
{
|
||||||
|
int32 index = fSources.IndexOf(source);
|
||||||
|
if (index < 0)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
fSources.RemoveItemAt(index);
|
||||||
|
delete source;
|
||||||
|
DataHistory* values = fValues.RemoveItemAt(index);
|
||||||
|
delete values;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::RemoveAllDataSources()
|
||||||
|
{
|
||||||
|
fSources.MakeEmpty();
|
||||||
|
fValues.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BMessage refresh(kMsgRefresh);
|
||||||
|
fRunner = new BMessageRunner(this, &refresh, fRefreshInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::DetachedFromWindow()
|
||||||
|
{
|
||||||
|
delete fRunner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::FrameResized(float /*width*/, float /*height*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::MouseDown(BPoint where)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
int32 buttons = B_PRIMARY_MOUSE_BUTTON;
|
||||||
|
int32 clicks = 1;
|
||||||
|
if (Looper() != NULL && Looper()->CurrentMessage() != NULL) {
|
||||||
|
Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
|
||||||
|
Looper()->CurrentMessage()->FindInt32("clicks", &clicks);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
|
||||||
|
menu->SetFont(be_plain_font);
|
||||||
|
BMenuItem* item;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < DataSource::CountSources(); i++) {
|
||||||
|
const DataSource* source = DataSource::SourceAt(i);
|
||||||
|
|
||||||
|
BMessage* message = new BMessage(kMsgToggleDataSource);
|
||||||
|
message->AddInt32("index", i);
|
||||||
|
|
||||||
|
item = new BMenuItem(source->Label(), message);
|
||||||
|
if (FindDataSource(source->Label()))
|
||||||
|
item->SetMarked(true);
|
||||||
|
|
||||||
|
menu->AddItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu->SetTargetForItems(this);
|
||||||
|
|
||||||
|
ConvertToScreen(&where);
|
||||||
|
menu->Go(where, true, false, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::MouseMoved(BPoint where, uint32 transit,
|
||||||
|
const BMessage* dragMessage)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case B_ABOUT_REQUESTED:
|
||||||
|
ActivityMonitor::ShowAbout();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgRefresh:
|
||||||
|
_Refresh();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgToggleDataSource:
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
if (message->FindInt32("index", &index) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const DataSource* baseSource = DataSource::SourceAt(index);
|
||||||
|
if (baseSource == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
DataSource* source = FindDataSource(baseSource->Label());
|
||||||
|
if (source == NULL)
|
||||||
|
AddDataSource(baseSource->Copy());
|
||||||
|
else
|
||||||
|
RemoveDataSource(source);
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
|
{
|
||||||
|
float deltaY = 0.0f;
|
||||||
|
if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK
|
||||||
|
|| deltaY == 0.0f)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (deltaY > 0)
|
||||||
|
fDrawResolution *= 2;
|
||||||
|
else
|
||||||
|
fDrawResolution /= 2;
|
||||||
|
|
||||||
|
if (fDrawResolution < 1)
|
||||||
|
fDrawResolution = 1;
|
||||||
|
if (fDrawResolution > 128)
|
||||||
|
fDrawResolution = 128;
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
|
||||||
|
int64 value)
|
||||||
|
{
|
||||||
|
int64 min = source->Minimum();
|
||||||
|
int64 max = source->Maximum();
|
||||||
|
if (source->AdaptiveScale()) {
|
||||||
|
int64 adaptiveMax = int64(values->MaximumValue() * 1.2);
|
||||||
|
if (adaptiveMax < max)
|
||||||
|
max = adaptiveMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > max)
|
||||||
|
value = max;
|
||||||
|
if (value < min)
|
||||||
|
value = min;
|
||||||
|
|
||||||
|
float height = Bounds().Height();
|
||||||
|
return height - (value - min) * height / (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::Draw(BRect /*updateRect*/)
|
||||||
|
{
|
||||||
|
uint32 step = 2;
|
||||||
|
uint32 resolution = fDrawResolution;
|
||||||
|
if (fDrawResolution > 1) {
|
||||||
|
step = 1;
|
||||||
|
resolution--;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 width = Bounds().IntegerWidth() - 10;
|
||||||
|
uint32 steps = width / step;
|
||||||
|
bigtime_t timeStep = fRefreshInterval * resolution;
|
||||||
|
bigtime_t now = system_time();
|
||||||
|
|
||||||
|
SetPenSize(2);
|
||||||
|
|
||||||
|
for (uint32 i = fSources.CountItems(); i-- > 0;) {
|
||||||
|
DataSource* source = fSources.ItemAt(i);
|
||||||
|
DataHistory* values = fValues.ItemAt(i);
|
||||||
|
bigtime_t time = now - steps * timeStep;
|
||||||
|
// for now steps pixels per second
|
||||||
|
|
||||||
|
BeginLineArray(steps);
|
||||||
|
SetHighColor(source->Color());
|
||||||
|
|
||||||
|
float lastY = FLT_MIN;
|
||||||
|
uint32 lastX = 0;
|
||||||
|
|
||||||
|
for (uint32 x = 0; x < width; x += step, time += timeStep) {
|
||||||
|
// TODO: compute starting point instead!
|
||||||
|
if (values->Start() > time || values->End() < time)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int64 value = values->ValueAt(time);
|
||||||
|
if (timeStep > fRefreshInterval) {
|
||||||
|
// TODO: always start with the same index, so that it always
|
||||||
|
// uses the same values for computation (currently it jumps)
|
||||||
|
uint32 count = 1;
|
||||||
|
for (bigtime_t offset = fRefreshInterval; offset < timeStep;
|
||||||
|
offset += fRefreshInterval) {
|
||||||
|
// TODO: handle int64 overflow correctly!
|
||||||
|
value += values->ValueAt(time + offset);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
value /= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
float y = _PositionForValue(source, values, value);
|
||||||
|
if (lastY != FLT_MIN)
|
||||||
|
AddLine(BPoint(lastX, lastY), BPoint(x, y), source->Color());
|
||||||
|
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndLineArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add marks when an app started or quit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::_Refresh()
|
||||||
|
{
|
||||||
|
SystemInfo info;
|
||||||
|
|
||||||
|
// TODO: run refresh in another thread to decouple it from the UI!
|
||||||
|
|
||||||
|
for (uint32 i = fSources.CountItems(); i-- > 0;) {
|
||||||
|
DataSource* source = fSources.ItemAt(i);
|
||||||
|
DataHistory* values = fValues.ItemAt(i);
|
||||||
|
|
||||||
|
int64 value = source->NextValue(info);
|
||||||
|
values->AddValue(info.Time(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bigtime_t now = info.Time();
|
||||||
|
if (fLastRefresh + fDrawInterval <= now) {
|
||||||
|
Invalidate();
|
||||||
|
fLastRefresh = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ACTIVITY_VIEW_H
|
||||||
|
#define ACTIVITY_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <View.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
#include "CircularBuffer.h"
|
||||||
|
|
||||||
|
class BMessageRunner;
|
||||||
|
class DataSource;
|
||||||
|
struct data_item;
|
||||||
|
|
||||||
|
|
||||||
|
class DataHistory {
|
||||||
|
public:
|
||||||
|
DataHistory(bigtime_t memorize, bigtime_t interval);
|
||||||
|
~DataHistory();
|
||||||
|
|
||||||
|
void AddValue(bigtime_t time, int64 value);
|
||||||
|
|
||||||
|
int64 ValueAt(bigtime_t time);
|
||||||
|
int64 MaximumValue() const;
|
||||||
|
int64 MinimumValue() const;
|
||||||
|
bigtime_t Start() const;
|
||||||
|
bigtime_t End() const;
|
||||||
|
|
||||||
|
void SetRefreshInterval(bigtime_t interval);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CircularBuffer<data_item> fBuffer;
|
||||||
|
int64 fMinimumValue;
|
||||||
|
int64 fMaximumValue;
|
||||||
|
bigtime_t fRefreshInterval;
|
||||||
|
int32 fLastIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ActivityView : public BView {
|
||||||
|
public:
|
||||||
|
ActivityView(BRect frame, const char* name,
|
||||||
|
const BMessage& settings, uint32 resizingMode);
|
||||||
|
ActivityView(BMessage* archive);
|
||||||
|
virtual ~ActivityView();
|
||||||
|
|
||||||
|
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||||
|
static BArchivable* Instantiate(BMessage* archive);
|
||||||
|
|
||||||
|
status_t SaveState(BMessage& state) const;
|
||||||
|
|
||||||
|
DataSource* FindDataSource(const char* name);
|
||||||
|
status_t AddDataSource(DataSource* source);
|
||||||
|
status_t RemoveDataSource(DataSource* source);
|
||||||
|
void RemoveAllDataSources();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void DetachedFromWindow();
|
||||||
|
|
||||||
|
virtual void FrameResized(float width, float height);
|
||||||
|
virtual void MouseDown(BPoint where);
|
||||||
|
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||||
|
const BMessage* dragMessage);
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Init(const BMessage* settings);
|
||||||
|
void _Refresh();
|
||||||
|
float _PositionForValue(DataSource* source,
|
||||||
|
DataHistory* values, int64 value);
|
||||||
|
|
||||||
|
rgb_color fBackgroundColor;
|
||||||
|
BObjectList<DataSource> fSources;
|
||||||
|
BObjectList<DataHistory> fValues;
|
||||||
|
BMessageRunner* fRunner;
|
||||||
|
bigtime_t fRefreshInterval;
|
||||||
|
bigtime_t fLastRefresh;
|
||||||
|
bigtime_t fDrawInterval;
|
||||||
|
int32 fDrawResolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ACTIVITY_VIEW_H
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ActivityWindow.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <Menu.h>
|
||||||
|
#include <MenuBar.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
|
||||||
|
#include "ActivityMonitor.h"
|
||||||
|
#include "ActivityView.h"
|
||||||
|
|
||||||
|
|
||||||
|
ActivityWindow::ActivityWindow()
|
||||||
|
: BWindow(BRect(100, 100, 500, 250), "ActivityMonitor", B_TITLED_WINDOW,
|
||||||
|
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
|
||||||
|
{
|
||||||
|
BMessage settings;
|
||||||
|
_LoadSettings(settings);
|
||||||
|
|
||||||
|
BRect frame;
|
||||||
|
if (settings.FindRect("window frame", &frame) == B_OK) {
|
||||||
|
MoveTo(frame.LeftTop());
|
||||||
|
ResizeTo(frame.Width(), frame.Height());
|
||||||
|
frame.OffsetTo(B_ORIGIN);
|
||||||
|
} else
|
||||||
|
frame = Bounds();
|
||||||
|
|
||||||
|
// create GUI
|
||||||
|
|
||||||
|
BMenuBar* menuBar = new BMenuBar(Bounds(), "menu");
|
||||||
|
AddChild(menuBar);
|
||||||
|
|
||||||
|
frame.top = menuBar->Frame().bottom;
|
||||||
|
|
||||||
|
BView* top = new BView(frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
|
||||||
|
top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
AddChild(top);
|
||||||
|
|
||||||
|
fActivityView = new ActivityView(top->Bounds().InsetByCopy(10, 10),
|
||||||
|
"ActivityMonitor", settings, B_FOLLOW_ALL);
|
||||||
|
top->AddChild(fActivityView);
|
||||||
|
|
||||||
|
// add menu
|
||||||
|
|
||||||
|
// "File" menu
|
||||||
|
BMenu* menu = new BMenu("File");
|
||||||
|
BMenuItem* item;
|
||||||
|
|
||||||
|
menu->AddItem(item = new BMenuItem("About ActivityMonitor" B_UTF8_ELLIPSIS,
|
||||||
|
new BMessage(B_ABOUT_REQUESTED)));
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
|
||||||
|
menu->SetTargetForItems(this);
|
||||||
|
item->SetTarget(be_app);
|
||||||
|
menuBar->AddItem(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ActivityWindow::~ActivityWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityWindow::_OpenSettings(BFile& file, uint32 mode)
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
path.Append("ActivityMonitor settings");
|
||||||
|
|
||||||
|
return file.SetTo(path.Path(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityWindow::_LoadSettings(BMessage& settings)
|
||||||
|
{
|
||||||
|
BFile file;
|
||||||
|
status_t status = _OpenSettings(file, B_READ_ONLY);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return settings.Unflatten(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ActivityWindow::_SaveSettings()
|
||||||
|
{
|
||||||
|
BFile file;
|
||||||
|
status_t status = _OpenSettings(file, B_WRITE_ONLY | B_CREATE_FILE
|
||||||
|
| B_ERASE_FILE);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
BMessage settings('actm');
|
||||||
|
status = settings.AddRect("window frame", Frame());
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.Flatten(&file);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityWindow::_MessageDropped(BMessage* message)
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
if (message->FindRef("refs", &ref) != B_OK) {
|
||||||
|
// TODO: If app, then launch it, and add ActivityView for this one?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
if (message->WasDropped()) {
|
||||||
|
_MessageDropped(message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message->what) {
|
||||||
|
case B_REFS_RECEIVED:
|
||||||
|
case B_SIMPLE_DATA:
|
||||||
|
_MessageDropped(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ActivityWindow::QuitRequested()
|
||||||
|
{
|
||||||
|
_SaveSettings();
|
||||||
|
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ACTIVITY_WINDOW_H
|
||||||
|
#define ACTIVITY_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
class BFile;
|
||||||
|
class ActivityView;
|
||||||
|
|
||||||
|
|
||||||
|
class ActivityWindow : public BWindow {
|
||||||
|
public:
|
||||||
|
ActivityWindow();
|
||||||
|
virtual ~ActivityWindow();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _OpenSettings(BFile& file, uint32 mode);
|
||||||
|
status_t _LoadSettings(BMessage& settings);
|
||||||
|
status_t _SaveSettings();
|
||||||
|
|
||||||
|
void _MessageDropped(BMessage *message);
|
||||||
|
|
||||||
|
ActivityView* fActivityView;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ACTIVITY_WINDOW_H
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CIRCULAR_BUFFER_H
|
||||||
|
#define CIRCULAR_BUFFER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
class CircularBuffer {
|
||||||
|
public:
|
||||||
|
CircularBuffer(size_t size)
|
||||||
|
:
|
||||||
|
fSize(size)
|
||||||
|
{
|
||||||
|
fBuffer = (Type *)malloc(fSize * sizeof(Type));
|
||||||
|
MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
~CircularBuffer()
|
||||||
|
{
|
||||||
|
free(fBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t InitCheck() const
|
||||||
|
{
|
||||||
|
return fBuffer != NULL ? B_OK : B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeEmpty()
|
||||||
|
{
|
||||||
|
fIn = 0;
|
||||||
|
fFirst = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const
|
||||||
|
{
|
||||||
|
return fIn == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 CountItems() const
|
||||||
|
{
|
||||||
|
return fIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type* ItemAt(int32 index) const
|
||||||
|
{
|
||||||
|
if (index >= (int32)fIn || index < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &fBuffer[(fFirst + index) % fSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddItem(const Type& item)
|
||||||
|
{
|
||||||
|
uint32 index;
|
||||||
|
if (fIn < fSize)
|
||||||
|
index = fFirst + fIn++;
|
||||||
|
else
|
||||||
|
index = fFirst++;
|
||||||
|
|
||||||
|
fBuffer[index % fSize] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fFirst;
|
||||||
|
uint32 fIn;
|
||||||
|
uint32 fSize;
|
||||||
|
Type* fBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CIRCULAR_BUFFER_H
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "DataSource.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "SystemInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
const DataSource* kSources[] = {
|
||||||
|
new UsedMemoryDataSource(),
|
||||||
|
new CachedMemoryDataSource(),
|
||||||
|
new ThreadsDataSource(),
|
||||||
|
new CpuUsageDataSource(),
|
||||||
|
};
|
||||||
|
const size_t kSourcesCount = sizeof(kSources) / sizeof(kSources[0]);
|
||||||
|
|
||||||
|
|
||||||
|
DataSource::DataSource(int64 initialMin, int64 initialMax)
|
||||||
|
:
|
||||||
|
fMinimum(initialMin),
|
||||||
|
fMaximum(initialMax),
|
||||||
|
fInterval(1000000LL),
|
||||||
|
fColor((rgb_color){200, 0, 0})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource::DataSource()
|
||||||
|
:
|
||||||
|
fMinimum(0),
|
||||||
|
fMaximum(100),
|
||||||
|
fInterval(1000000LL),
|
||||||
|
fColor((rgb_color){200, 0, 0})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource::DataSource(const DataSource& other)
|
||||||
|
{
|
||||||
|
fMinimum = other.fMinimum;
|
||||||
|
fMaximum = other.fMaximum;
|
||||||
|
fInterval = other.fInterval;
|
||||||
|
fColor = other.fColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource::~DataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
DataSource::Copy() const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
// this class cannot be copied
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
DataSource::Minimum() const
|
||||||
|
{
|
||||||
|
return fMinimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
DataSource::Maximum() const
|
||||||
|
{
|
||||||
|
return fMaximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
DataSource::RefreshInterval() const
|
||||||
|
{
|
||||||
|
return fInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DataSource::SetLimits(int64 min, int64 max)
|
||||||
|
{
|
||||||
|
fMinimum = min;
|
||||||
|
fMaximum = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DataSource::SetRefreshInterval(bigtime_t interval)
|
||||||
|
{
|
||||||
|
fInterval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DataSource::SetColor(rgb_color color)
|
||||||
|
{
|
||||||
|
fColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
DataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DataSource::Print(BString& text, int64 value) const
|
||||||
|
{
|
||||||
|
text = "";
|
||||||
|
text << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
DataSource::Label() const
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
DataSource::Unit() const
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rgb_color
|
||||||
|
DataSource::Color() const
|
||||||
|
{
|
||||||
|
return fColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DataSource::AdaptiveScale() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ int32
|
||||||
|
DataSource::CountSources()
|
||||||
|
{
|
||||||
|
return kSourcesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ const DataSource*
|
||||||
|
DataSource::SourceAt(int32 index)
|
||||||
|
{
|
||||||
|
if (index >= (int32)kSourcesCount || index < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return kSources[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
MemoryDataSource::MemoryDataSource()
|
||||||
|
{
|
||||||
|
SystemInfo info;
|
||||||
|
|
||||||
|
fMinimum = 0;
|
||||||
|
fMaximum = info.MaxMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MemoryDataSource::~MemoryDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MemoryDataSource::Print(BString& text, int64 value) const
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%.1g MB", value / 1048576.0);
|
||||||
|
|
||||||
|
text = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
MemoryDataSource::Unit() const
|
||||||
|
{
|
||||||
|
return "MB";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
UsedMemoryDataSource::UsedMemoryDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UsedMemoryDataSource::~UsedMemoryDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
UsedMemoryDataSource::Copy() const
|
||||||
|
{
|
||||||
|
return new UsedMemoryDataSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
UsedMemoryDataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
return info.UsedMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
UsedMemoryDataSource::Label() const
|
||||||
|
{
|
||||||
|
return "Available Memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
CachedMemoryDataSource::CachedMemoryDataSource()
|
||||||
|
{
|
||||||
|
fColor = (rgb_color){0, 200, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CachedMemoryDataSource::~CachedMemoryDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
CachedMemoryDataSource::Copy() const
|
||||||
|
{
|
||||||
|
return new CachedMemoryDataSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
CachedMemoryDataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
return info.CachedMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
CachedMemoryDataSource::Label() const
|
||||||
|
{
|
||||||
|
return "Cached Memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
ThreadsDataSource::ThreadsDataSource()
|
||||||
|
{
|
||||||
|
SystemInfo info;
|
||||||
|
|
||||||
|
fMinimum = 0;
|
||||||
|
fMaximum = info.MaxThreads();
|
||||||
|
|
||||||
|
fColor = (rgb_color){0, 0, 200};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ThreadsDataSource::~ThreadsDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
ThreadsDataSource::Copy() const
|
||||||
|
{
|
||||||
|
return new ThreadsDataSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
ThreadsDataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
return info.UsedThreads();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
ThreadsDataSource::Label() const
|
||||||
|
{
|
||||||
|
return "Threads";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ThreadsDataSource::AdaptiveScale() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
CpuUsageDataSource::CpuUsageDataSource()
|
||||||
|
:
|
||||||
|
fPreviousActive(0),
|
||||||
|
fPreviousTime(0)
|
||||||
|
{
|
||||||
|
fMinimum = 0;
|
||||||
|
fMaximum = 1000;
|
||||||
|
|
||||||
|
fColor = (rgb_color){200, 200, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CpuUsageDataSource::CpuUsageDataSource(const CpuUsageDataSource& other)
|
||||||
|
{
|
||||||
|
fPreviousActive = other.fPreviousActive;
|
||||||
|
fPreviousTime = other.fPreviousTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CpuUsageDataSource::~CpuUsageDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
CpuUsageDataSource::Copy() const
|
||||||
|
{
|
||||||
|
return new CpuUsageDataSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CpuUsageDataSource::Print(BString& text, int64 value) const
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%.1g%%", value / 10.0);
|
||||||
|
|
||||||
|
text = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
CpuUsageDataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
int32 running = 0;
|
||||||
|
bigtime_t active = 0;
|
||||||
|
|
||||||
|
for (int32 cpu = 0; cpu < info.Info().cpu_count; cpu++) {
|
||||||
|
active += info.Info().cpu_infos[cpu].active_time;
|
||||||
|
running++;
|
||||||
|
// TODO: take disabled CPUs into account
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 percent = int64(1000.0 * (active - fPreviousActive)
|
||||||
|
/ (running * (info.Time() - fPreviousTime)));
|
||||||
|
if (percent < 0)
|
||||||
|
percent = 0;
|
||||||
|
if (percent > 1000)
|
||||||
|
percent = 1000;
|
||||||
|
|
||||||
|
fPreviousActive = active;
|
||||||
|
fPreviousTime = info.Time();
|
||||||
|
|
||||||
|
return percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
CpuUsageDataSource::Label() const
|
||||||
|
{
|
||||||
|
return "CPU Usage";
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DATA_SOURCE_H
|
||||||
|
#define DATA_SOURCE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <InterfaceDefs.h>
|
||||||
|
|
||||||
|
class BString;
|
||||||
|
class SystemInfo;
|
||||||
|
|
||||||
|
|
||||||
|
class DataSource {
|
||||||
|
public:
|
||||||
|
DataSource(int64 initialMin, int64 initialMax);
|
||||||
|
DataSource();
|
||||||
|
DataSource(const DataSource& other);
|
||||||
|
virtual ~DataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
|
int64 Minimum() const;
|
||||||
|
int64 Maximum() const;
|
||||||
|
bigtime_t RefreshInterval() const;
|
||||||
|
|
||||||
|
virtual void SetLimits(int64 min, int64 max);
|
||||||
|
virtual void SetRefreshInterval(bigtime_t interval);
|
||||||
|
virtual void SetColor(rgb_color color);
|
||||||
|
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
virtual void Print(BString& text, int64 value) const;
|
||||||
|
|
||||||
|
virtual const char* Label() const;
|
||||||
|
virtual const char* Unit() const;
|
||||||
|
virtual rgb_color Color() const;
|
||||||
|
virtual bool AdaptiveScale() const;
|
||||||
|
|
||||||
|
static int32 CountSources();
|
||||||
|
static const DataSource* SourceAt(int32 index);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int64 fMinimum;
|
||||||
|
int64 fMaximum;
|
||||||
|
bigtime_t fInterval;
|
||||||
|
rgb_color fColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MemoryDataSource : public DataSource {
|
||||||
|
public:
|
||||||
|
MemoryDataSource();
|
||||||
|
virtual ~MemoryDataSource();
|
||||||
|
|
||||||
|
virtual void Print(BString& text, int64 value) const;
|
||||||
|
virtual const char* Unit() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class UsedMemoryDataSource : public MemoryDataSource {
|
||||||
|
public:
|
||||||
|
UsedMemoryDataSource();
|
||||||
|
virtual ~UsedMemoryDataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
virtual const char* Label() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CachedMemoryDataSource : public MemoryDataSource {
|
||||||
|
public:
|
||||||
|
CachedMemoryDataSource();
|
||||||
|
virtual ~CachedMemoryDataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
virtual const char* Label() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadsDataSource : public DataSource {
|
||||||
|
public:
|
||||||
|
ThreadsDataSource();
|
||||||
|
virtual ~ThreadsDataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
virtual const char* Label() const;
|
||||||
|
virtual bool AdaptiveScale() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CpuUsageDataSource : public DataSource {
|
||||||
|
public:
|
||||||
|
CpuUsageDataSource();
|
||||||
|
CpuUsageDataSource(const CpuUsageDataSource& other);
|
||||||
|
virtual ~CpuUsageDataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
|
virtual void Print(BString& text, int64 value) const;
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
virtual const char* Label() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bigtime_t fPreviousActive;
|
||||||
|
bigtime_t fPreviousTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DATA_SOURCE_H
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
SubDir HAIKU_TOP src apps activitymonitor ;
|
||||||
|
|
||||||
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
|
Application ActivityMonitor :
|
||||||
|
ActivityMonitor.cpp
|
||||||
|
ActivityView.cpp
|
||||||
|
ActivityWindow.cpp
|
||||||
|
DataSource.cpp
|
||||||
|
SystemInfo.cpp
|
||||||
|
|
||||||
|
: be tracker $(TARGET_LIBSTDC++)
|
||||||
|
: ActivityMonitor.rdef
|
||||||
|
;
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "SystemInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
SystemInfo::SystemInfo()
|
||||||
|
:
|
||||||
|
fTime(system_time())
|
||||||
|
{
|
||||||
|
get_system_info(&fSystemInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SystemInfo::~SystemInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
SystemInfo::CachedMemory() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.cached_pages * B_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
SystemInfo::UsedMemory() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.used_pages * B_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
SystemInfo::MaxMemory() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.max_pages * B_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
SystemInfo::UsedThreads() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.used_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
SystemInfo::MaxThreads() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.max_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
SystemInfo::UsedTeams() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.used_teams;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
SystemInfo::MaxTeams() const
|
||||||
|
{
|
||||||
|
return fSystemInfo.max_teams;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef SYSTEM_INFO_H
|
||||||
|
#define SYSTEM_INFO_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
|
class SystemInfo {
|
||||||
|
public:
|
||||||
|
SystemInfo();
|
||||||
|
~SystemInfo();
|
||||||
|
|
||||||
|
uint64 CachedMemory() const;
|
||||||
|
uint64 UsedMemory() const;
|
||||||
|
uint64 MaxMemory() const;
|
||||||
|
|
||||||
|
uint32 UsedThreads() const;
|
||||||
|
uint32 MaxThreads() const;
|
||||||
|
|
||||||
|
uint32 UsedTeams() const;
|
||||||
|
uint32 MaxTeams() const;
|
||||||
|
|
||||||
|
bigtime_t Time() const { return fTime; }
|
||||||
|
const system_info& Info() const { return fSystemInfo; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
system_info fSystemInfo;
|
||||||
|
bigtime_t fTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYSTEM_INFO_H
|
||||||
Reference in New Issue
Block a user