xref: /haiku/src/apps/cortex/ParameterView/ParameterWindowManager.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 // ParameterWindowManager.cpp
2 
3 #include "ParameterWindowManager.h"
4 #include "ParameterWindow.h"
5 // NodeManager
6 #include "NodeRef.h"
7 
8 // Application Kit
9 #include <AppDefs.h>
10 // Media Kit
11 #include <MediaRoster.h>
12 // Support Kit
13 #include <List.h>
14 
15 __USE_CORTEX_NAMESPACE
16 
17 #include <Debug.h>
18 #define D_ACCESS(x) //PRINT (x)
19 #define D_ALLOC(x) //PRINT (x)
20 #define D_INTERNAL(x) //PRINT (x)
21 #define D_MESSAGE(x) //PRINT (x)
22 #define D_WINDOW(x) //PRINT (x)
23 
24 // -------------------------------------------------------- //
25 // internal types
26 // -------------------------------------------------------- //
27 
28 // used to remember the list of ParameterWindows
29 struct window_map_entry {
30 
31 public:						// *** ctor/dtor
32 
33 							window_map_entry(
34 								const NodeRef *ref,
35 								BWindow *window)
36 								: ref(ref),
37 								  window(window)
38 							{ }
39 
40 public:						// *** data members
41 
42 	const NodeRef		   *ref;
43 
44 	BWindow				   *window;
45 };
46 
47 // used to remember the list of ControlPanels
48 struct panel_map_entry {
49 
50 public:						// *** ctor/dtor
51 
52 							panel_map_entry(
53 								int32 id,
54 								const BMessenger &messenger)
55 								: id(id),
56 								  messenger(messenger)
57 							{ }
58 
59 public:						// *** data members
60 
61 	int32					id;
62 
63 	const BMessenger		messenger;
64 };
65 
66 // -------------------------------------------------------- //
67 // static member init
68 // -------------------------------------------------------- //
69 
70 const BPoint ParameterWindowManager::M_DEFAULT_OFFSET	= BPoint(20.0, 20.0);
71 const BPoint ParameterWindowManager::M_INIT_POSITION	= BPoint(90.0, 90.0);
72 
73 ParameterWindowManager *ParameterWindowManager::s_instance = 0;
74 
75 // -------------------------------------------------------- //
76 // *** ctor/dtor
77 // -------------------------------------------------------- //
78 
79 /* hidden */
80 ParameterWindowManager::ParameterWindowManager()
81 	: BLooper("ParameterWindowManager",
82 			  B_NORMAL_PRIORITY),
83 	  m_windowList(0),
84 	  m_panelList(0),
85 	  m_lastWindowPosition(M_INIT_POSITION - M_DEFAULT_OFFSET) {
86 	D_ALLOC(("ParameterWindowManager::ParameterWindowManager()\n"));
87 
88 	m_windowList = new BList();
89 	m_panelList = new BList();
90 	Run();
91 }
92 
93 ParameterWindowManager::~ParameterWindowManager() {
94 	D_ALLOC(("ParameterWindowManager::~ParameterWindowManager()\n"));
95 
96 	while (m_windowList->CountItems() > 0) {
97 		window_map_entry *entry = static_cast<window_map_entry *>
98 								  (m_windowList->ItemAt(0));
99 		if (entry && entry->window) {
100 			remove_observer(this, entry->ref);
101 			entry->window->Lock();
102 			entry->window->Quit();
103 		}
104 		m_windowList->RemoveItem(reinterpret_cast<void *>(entry));
105 		delete entry;
106 	}
107 	delete m_windowList;
108 
109 	while (m_panelList->CountItems() > 0) {
110 		panel_map_entry *entry = static_cast<panel_map_entry *>
111 								 (m_panelList->ItemAt(0));
112 		if (entry && entry->messenger.IsValid()) {
113 			entry->messenger.SendMessage(B_QUIT_REQUESTED);
114 		}
115 		m_panelList->RemoveItem(reinterpret_cast<void *>(entry));
116 		delete entry;
117 	}
118 	delete m_panelList;
119 
120 	s_instance = 0;
121 }
122 
123 // -------------------------------------------------------- //
124 // *** singleton access
125 // -------------------------------------------------------- //
126 
127 /*static*/
128 ParameterWindowManager *ParameterWindowManager::Instance() {
129 	D_ACCESS(("ParameterWindowManager::Instance()\n"));
130 
131 	if (!s_instance) {
132 		D_ACCESS((" -> create instance\n"));
133 		s_instance = new ParameterWindowManager();
134 	}
135 
136 	return s_instance;
137 }
138 
139 /* static */
140 void ParameterWindowManager::shutDown() {
141 	D_WINDOW(("ParameterWindowManager::shutDown()\n"));
142 
143 	if (s_instance) {
144 		s_instance->Lock();
145 		s_instance->Quit();
146 	}
147 }
148 
149 // -------------------------------------------------------- //
150 // *** operations
151 // -------------------------------------------------------- //
152 
153 status_t ParameterWindowManager::openWindowFor(
154 	const NodeRef *ref) {
155 	D_WINDOW(("ParameterWindowManager::openWindowFor()\n"));
156 
157 	// make absolutely sure we're locked
158 	if (!IsLocked()) {
159 		debugger("The looper must be locked !");
160 	}
161 
162 	// make sure the ref is valid
163 	if (!ref) {
164 		return B_ERROR;
165 	}
166 
167 	BWindow *window = 0;
168 	if (_findWindowFor(ref->id(), &window)) {
169 		// window for this node already exists, activate it
170 		window->SetWorkspaces(B_CURRENT_WORKSPACE);
171 		window->Activate();
172 		return B_OK;
173 	}
174 
175 	BMessenger messenger(0, this);
176 	live_node_info nodeInfo = ref->nodeInfo();
177 	m_lastWindowPosition += M_DEFAULT_OFFSET;
178 	window = new ParameterWindow(m_lastWindowPosition,
179 								 nodeInfo, &messenger);
180 	if (_addWindowFor(ref, window)) {
181 		window->Show();
182 		return B_OK;
183 	}
184 	delete window;
185 
186 	return B_ERROR;
187 }
188 
189 status_t ParameterWindowManager::startControlPanelFor(
190 	const NodeRef *ref) {
191 	D_WINDOW(("ParameterWindowManager::startControlPanelFor()\n"));
192 
193 	// make absolutely sure we're locked
194 	if (!IsLocked()) {
195 		debugger("The looper must be locked !");
196 	}
197 
198 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
199 	if (!roster) {
200 		D_WINDOW((" -> MediaRoster not available\n"));
201 		return B_ERROR;
202 	}
203 
204 	BMessenger messenger;
205 	if (_findPanelFor(ref->id(), &messenger)) {
206 		// find out if the messengers target still exists
207 		if (messenger.IsValid()) {
208 			return B_OK;
209 		}
210 		else {
211 			_removePanelFor(ref->id());
212 		}
213 	}
214 
215 	status_t error = roster->StartControlPanel(ref->node(),
216 											   &messenger);
217 	if (error) {
218 		D_INTERNAL((" -> StartControlPanel() failed (%s)\n",
219 					strerror(error)));
220 		return error;
221 	}
222 
223 	_addPanelFor(ref->id(), messenger);
224 	return B_OK;
225 }
226 
227 // -------------------------------------------------------- //
228 // *** BLooper impl
229 // -------------------------------------------------------- //
230 
231 void ParameterWindowManager::MessageReceived(
232 	BMessage *message) {
233 	D_MESSAGE(("ParameterWindowManager::MessageReceived()\n"));
234 
235 	switch (message->what) {
236 		case ParameterWindow::M_CLOSED: {
237 			D_MESSAGE((" -> ParameterWindow::M_CLOSED\n"));
238 			int32 nodeID;
239 			if (message->FindInt32("nodeID", &nodeID) != B_OK) {
240 				return;
241 			}
242 			_removeWindowFor(nodeID);
243 			break;
244 		}
245 		case ParameterWindow::M_CONTROL_PANEL_STARTED: {
246 			D_MESSAGE((" -> ParameterWindow::M_CONTROL_PANEL_STARTED\n"));
247 			int32 nodeID;
248 			if (message->FindInt32("nodeID", &nodeID) != B_OK) {
249 				return;
250 			}
251 			BMessenger messenger;
252 			if (message->FindMessenger("messenger", &messenger) != B_OK) {
253 				return;
254 			}
255 			_addPanelFor(nodeID, messenger);
256 			break;
257 		}
258 		case NodeRef::M_RELEASED: {
259 			D_MESSAGE((" -> NodeRef::M_RELEASED\n"));
260 			int32 nodeID;
261 			if (message->FindInt32("nodeID", &nodeID) != B_OK) {
262 				return;
263 			}
264 			BWindow *window;
265 			if (_findWindowFor(nodeID, &window)) {
266 				window->Lock();
267 				window->Quit();
268 				_removeWindowFor(nodeID);
269 			}
270 			break;
271 		}
272 		default: {
273 			BLooper::MessageReceived(message);
274 		}
275 	}
276 }
277 
278 // -------------------------------------------------------- //
279 // *** internal operations
280 // -------------------------------------------------------- //
281 
282 bool ParameterWindowManager::_addWindowFor(
283 	const NodeRef *ref,
284 	BWindow *window) {
285 	D_INTERNAL(("ParameterWindowManager::_addWindowFor()\n"));
286 
287 	window_map_entry *entry = new window_map_entry(ref,
288 												   window);
289 	if (m_windowList->AddItem(reinterpret_cast<void *>(entry))) {
290 		add_observer(this, entry->ref);
291 		return true;
292 	}
293 
294 	return false;
295 }
296 
297 bool ParameterWindowManager::_findWindowFor(
298 	int32 id,
299 	BWindow **outWindow) {
300 	D_INTERNAL(("ParameterWindowManager::_findWindowFor()\n"));
301 
302 	for (int32 i = 0; i < m_windowList->CountItems(); i++) {
303 		window_map_entry *entry = static_cast<window_map_entry *>
304 								  (m_windowList->ItemAt(i));
305 		if (entry->ref->id() == id) {
306 			*outWindow = entry->window;
307 			return true;
308 		}
309 	}
310 
311 	return false;
312 }
313 
314 void ParameterWindowManager::_removeWindowFor(
315 	int32 id) {
316 	D_INTERNAL(("ParameterWindowManager::_removeWindowFor()\n"));
317 
318 	for (int32 i = 0; i < m_windowList->CountItems(); i++) {
319 		window_map_entry *entry = static_cast<window_map_entry *>
320 								  (m_windowList->ItemAt(i));
321 		if (entry->ref->id() == id) {
322 			m_windowList->RemoveItem(reinterpret_cast<void *>(entry));
323 			remove_observer(this, entry->ref);
324 			delete entry;
325 		}
326 	}
327 
328 	// try to shutdown
329 	if (m_windowList->CountItems() == 0) {
330 		int32 i = 0;
331 		while (true) {
332 			// take all invalid messengers out of the panel list
333 			panel_map_entry *entry = static_cast<panel_map_entry *>
334 									 (m_panelList->ItemAt(i));
335 			if (!entry) {
336 				// end of list
337 				break;
338 			}
339 			if (!entry->messenger.IsValid()) {
340 				// this control panel doesn't exist anymore
341 				m_panelList->RemoveItem(entry);
342 				continue;
343 			}
344 		}
345 		if (m_panelList->CountItems() == 0) {
346 			// neither windows nor panels to manage, go to sleep
347 			PostMessage(B_QUIT_REQUESTED);
348 		}
349 	}
350 }
351 
352 bool ParameterWindowManager::_addPanelFor(
353 	int32 id,
354 	const BMessenger &messenger) {
355 	D_INTERNAL(("ParameterWindowManager::_addPanelFor()\n"));
356 
357 	panel_map_entry *entry = new panel_map_entry(id,
358 												 messenger);
359 	if (m_panelList->AddItem(reinterpret_cast<void *>(entry))) {
360 		return true;
361 	}
362 
363 	return false;
364 }
365 
366 bool ParameterWindowManager::_findPanelFor(
367 	int32 id,
368 	BMessenger *outMessenger) {
369 	D_INTERNAL(("ParameterWindowManager::_findPanelFor()\n"));
370 
371 	for (int32 i = 0; i < m_panelList->CountItems(); i++) {
372 		panel_map_entry *entry = static_cast<panel_map_entry *>
373 								 (m_panelList->ItemAt(i));
374 		if (entry->id == id) {
375 			*outMessenger = entry->messenger;
376 			return true;
377 		}
378 	}
379 
380 	return false;
381 }
382 
383 void ParameterWindowManager::_removePanelFor(
384 	int32 id) {
385 	D_INTERNAL(("ParameterWindowManager::_removeWindowFor()\n"));
386 
387 	for (int32 i = 0; i < m_panelList->CountItems(); i++) {
388 		panel_map_entry *entry = static_cast<panel_map_entry *>
389 								 (m_panelList->ItemAt(i));
390 		if (entry->id == id) {
391 			m_panelList->RemoveItem(reinterpret_cast<void *>(entry));
392 			delete entry;
393 		}
394 	}
395 }
396 
397 // END -- ParameterWindowManager.cpp --
398