1/*
2 * Copyright 2008, Fran��ois Revol, revol@free.fr. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "SystemInfoHandler.h"
8
9#include <stdlib.h>
10#include <string.h>
11#include <unistd.h>
12
13#include <Clipboard.h>
14#include <Handler.h>
15#include <Input.h>
16#include <List.h>
17#include <MediaRoster.h>
18#include <Messenger.h>
19#include <Roster.h>
20
21
22SystemInfoHandler::SystemInfoHandler()
23	: BHandler("SystemInfoHandler")
24{
25	fRunningApps = 0;
26	fClipboardSize = 0;
27	fClipboardTextSize = 0;
28	fMediaNodes = 0;
29	fMediaConnections = 0;
30	fMediaBuffers = 0;
31}
32
33
34SystemInfoHandler::~SystemInfoHandler()
35{
36}
37
38
39status_t
40SystemInfoHandler::Archive(BMessage* data, bool deep) const
41{
42	// we don't want ourselves to be archived at all...
43	// return BHandler::Archive(data, deep);
44	return B_OK;
45}
46
47
48void
49SystemInfoHandler::StartWatching()
50{
51	status_t status;
52	fRunningApps = 0;
53	fClipboardSize = 0;
54	fClipboardTextSize = 0;
55	fMediaNodes = 0;
56	fMediaConnections = 0;
57	fMediaBuffers = 0;
58
59	// running applications count
60	BList teamList;
61	if (be_roster) {
62		be_roster->StartWatching(BMessenger(this),
63			B_REQUEST_LAUNCHED | B_REQUEST_QUIT);
64		be_roster->GetAppList(&teamList);
65		fRunningApps = teamList.CountItems();
66		teamList.MakeEmpty();
67	}
68
69	// useless clipboard size
70	if (be_clipboard) {
71		be_clipboard->StartWatching(BMessenger(this));
72		_UpdateClipboardData();
73	}
74
75	if (BMediaRoster::Roster(&status) && (status >= B_OK)) {
76		BMediaRoster::Roster()->StartWatching(BMessenger(this), B_MEDIA_NODE_CREATED);
77		BMediaRoster::Roster()->StartWatching(BMessenger(this), B_MEDIA_NODE_DELETED);
78		BMediaRoster::Roster()->StartWatching(BMessenger(this), B_MEDIA_CONNECTION_MADE);
79		BMediaRoster::Roster()->StartWatching(BMessenger(this), B_MEDIA_CONNECTION_BROKEN);
80		BMediaRoster::Roster()->StartWatching(BMessenger(this), B_MEDIA_BUFFER_CREATED);
81		BMediaRoster::Roster()->StartWatching(BMessenger(this), B_MEDIA_BUFFER_DELETED);
82		// XXX: this won't survive a media_server restart...
83
84		live_node_info nodeInfo; // I just need one
85		int32 nodeCount = 1;
86		if (BMediaRoster::Roster()->GetLiveNodes(&nodeInfo, &nodeCount)) {
87			if (nodeCount > 0)
88				fMediaNodes = (uint32)nodeCount;
89			// TODO: retry with an array, and use GetNodeInput/Output
90			// to find initial connection count
91		}
92		// TODO: get initial buffer count
93
94	}
95
96	// doesn't work on R5
97	watch_input_devices(BMessenger(this), true);
98}
99
100
101void
102SystemInfoHandler::StopWatching()
103{
104	status_t status;
105	watch_input_devices(BMessenger(this), false);
106	if (BMediaRoster::Roster(&status) && (status >= B_OK)) {
107		BMediaRoster::Roster()->StopWatching(BMessenger(this), B_MEDIA_NODE_CREATED);
108		BMediaRoster::Roster()->StopWatching(BMessenger(this), B_MEDIA_NODE_DELETED);
109		BMediaRoster::Roster()->StopWatching(BMessenger(this), B_MEDIA_CONNECTION_MADE);
110		BMediaRoster::Roster()->StopWatching(BMessenger(this), B_MEDIA_CONNECTION_BROKEN);
111		BMediaRoster::Roster()->StopWatching(BMessenger(this), B_MEDIA_BUFFER_CREATED);
112		BMediaRoster::Roster()->StopWatching(BMessenger(this), B_MEDIA_BUFFER_DELETED);
113	}
114	if (be_clipboard)
115		be_clipboard->StopWatching(BMessenger(this));
116	if (be_roster)
117		be_roster->StopWatching(BMessenger(this));
118}
119
120
121void
122SystemInfoHandler::MessageReceived(BMessage* message)
123{
124	switch (message->what) {
125		case B_SOME_APP_LAUNCHED:
126			fRunningApps++;
127			// TODO: maybe resync periodically in case we miss one
128			break;
129		case B_SOME_APP_QUIT:
130			fRunningApps--;
131			// TODO: maybe resync periodically in case we miss one
132			break;
133		case B_CLIPBOARD_CHANGED:
134			_UpdateClipboardData();
135			break;
136		case B_MEDIA_NODE_CREATED:
137			fMediaNodes++;
138			break;
139		case B_MEDIA_NODE_DELETED:
140			fMediaNodes--;
141			break;
142		case B_MEDIA_CONNECTION_MADE:
143			fMediaConnections++;
144			break;
145		case B_MEDIA_CONNECTION_BROKEN:
146			fMediaConnections--;
147			break;
148		case B_MEDIA_BUFFER_CREATED:
149			fMediaBuffers++;
150			break;
151		case B_MEDIA_BUFFER_DELETED:
152			fMediaBuffers--;
153			break;
154		default:
155			message->PrintToStream();
156			BHandler::MessageReceived(message);
157	}
158}
159
160
161uint32
162SystemInfoHandler::RunningApps() const
163{
164	return fRunningApps;
165}
166
167
168uint32
169SystemInfoHandler::ClipboardSize() const
170{
171	return fClipboardSize;
172}
173
174
175uint32
176SystemInfoHandler::ClipboardTextSize() const
177{
178	return fClipboardTextSize;
179}
180
181
182uint32
183SystemInfoHandler::MediaNodes() const
184{
185	return fMediaNodes;
186}
187
188
189uint32
190SystemInfoHandler::MediaConnections() const
191{
192	return fMediaConnections;
193}
194
195
196uint32
197SystemInfoHandler::MediaBuffers() const
198{
199	return fMediaBuffers;
200}
201
202
203void
204SystemInfoHandler::_UpdateClipboardData()
205{
206	fClipboardSize = 0;
207	fClipboardTextSize = 0;
208
209	if (be_clipboard == NULL || !be_clipboard->Lock())
210		return;
211
212	BMessage* data = be_clipboard->Data();
213	if (data) {
214		ssize_t size = data->FlattenedSize();
215		fClipboardSize = size < 0 ? 0 : (uint32)size;
216
217		const void* text;
218		ssize_t textSize;
219		if (data->FindData("text/plain", B_MIME_TYPE, &text, &textSize) >= B_OK)
220			fClipboardTextSize = textSize;
221	}
222
223	be_clipboard->Unlock();
224}
225
226