xref: /haiku/src/apps/cortex/InfoView/InfoWindowManager.cpp (revision b55a57da7173b9af0432bd3e148d03f06161d036)
1 // InfoWindowManager.cpp
2 
3 #include "InfoWindowManager.h"
4 // InfoWindow
5 #include "AppNodeInfoView.h"
6 #include "ConnectionInfoView.h"
7 #include "DormantNodeInfoView.h"
8 #include "EndPointInfoView.h"
9 #include "FileNodeInfoView.h"
10 #include "LiveNodeInfoView.h"
11 #include "InfoWindow.h"
12 // NodeManager
13 #include "AddOnHostProtocol.h"
14 #include "Connection.h"
15 #include "NodeRef.h"
16 
17 // Application Kit
18 #include <Application.h>
19 #include <AppDefs.h>
20 #include <Roster.h>
21 // Media Kit
22 #include <MediaAddOn.h>
23 #include <MediaRoster.h>
24 // Support Kit
25 #include <List.h>
26 
27 __USE_CORTEX_NAMESPACE
28 
29 #include <Debug.h>
30 #define D_ACCESS(x) //PRINT (x)
31 #define D_ALLOC(x) //PRINT (x)
32 #define D_INTERNAL(x) //PRINT (x)
33 #define D_MESSAGE(x) //PRINT (x)
34 #define D_WINDOW(x) //PRINT (x)
35 
36 // -------------------------------------------------------- //
37 // internal types
38 // -------------------------------------------------------- //
39 
40 // used to remember window for live nodes
41 struct live_node_window {
42 
43 public:						// *** ctor/dtor
44 
45 							live_node_window(
46 								const NodeRef *ref,
47 								BWindow *window)
48 								: ref(ref),
49 								  window(window)
50 							{ }
51 
52 public:						// *** data members
53 
54 	const NodeRef		   *ref;
55 
56 	BWindow				   *window;
57 };
58 
59 // used to remember windows for dormant nodes
60 struct dormant_node_window {
61 
62 public:						// *** ctor/dtor
63 
64 							dormant_node_window(
65 								const dormant_node_info &info,
66 								BWindow *window)
67 								: info(info),
68 								  window(window)
69 							{ }
70 
71 public:						// *** data members
72 
73 	const dormant_node_info	info;
74 
75 	BWindow				   *window;
76 };
77 
78 // used to remember windows for connections
79 struct connection_window {
80 
81 public:						// *** ctor/dtor
82 
83 							connection_window(
84 								const media_source &source,
85 								const media_destination &destination,
86 								BWindow *window)
87 								: source(source),
88 								  destination(destination),
89 								  window(window)
90 							{ }
91 
92 public:						// *** data members
93 
94 	media_source			source;
95 
96 	media_destination		destination;
97 
98 	BWindow				   *window;
99 };
100 
101 // used to remember windows for media_inputs
102 struct input_window {
103 
104 public:						// *** ctor/dtor
105 
106 							input_window(
107 								const media_destination &destination,
108 								BWindow *window)
109 								: destination(destination),
110 								  window(window)
111 							{ }
112 
113 public:						// *** data members
114 
115 	media_destination		destination;
116 
117 	BWindow				   *window;
118 };
119 
120 // used to remember windows for media_outputs
121 struct output_window {
122 
123 public:						// *** ctor/dtor
124 
125 							output_window(
126 								const media_source &source,
127 								BWindow *window)
128 								: source(source),
129 								  window(window)
130 							{ }
131 
132 public:						// *** data members
133 
134 	media_source			source;
135 
136 	BWindow				   *window;
137 };
138 
139 // -------------------------------------------------------- //
140 // static member init
141 // -------------------------------------------------------- //
142 
143 const BPoint InfoWindowManager::M_DEFAULT_OFFSET	= BPoint(20.0, 20.0);
144 const BPoint InfoWindowManager::M_INIT_POSITION	= BPoint(90.0, 90.0);
145 
146 InfoWindowManager *InfoWindowManager::s_instance = 0;
147 
148 // -------------------------------------------------------- //
149 // *** ctor/dtor
150 // -------------------------------------------------------- //
151 
152 /* hidden */
153 InfoWindowManager::InfoWindowManager()
154 	: BLooper("InfoWindowManager",
155 			  B_NORMAL_PRIORITY),
156 	  m_liveNodeWindows(0),
157 	  m_dormantNodeWindows(0),
158 	  m_connectionWindows(0),
159 	  m_inputWindows(0),
160 	  m_outputWindows(0),
161 	  m_nextWindowPosition(M_INIT_POSITION) {
162 	D_ALLOC(("InfoWindowManager::InfoWindowManager()\n"));
163 
164 	Run();
165 
166 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
167 	if (roster) {
168 		roster->StartWatching(BMessenger(0, this),
169 							  B_MEDIA_CONNECTION_BROKEN);
170 	}
171 }
172 
173 InfoWindowManager::~InfoWindowManager() {
174 	D_ALLOC(("InfoWindowManager::~InfoWindowManager()\n"));
175 
176 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
177 	if (roster) {
178 		roster->StopWatching(BMessenger(0, this),
179 							  B_MEDIA_CONNECTION_BROKEN);
180 	}
181 
182 	if (m_liveNodeWindows) {
183 		while (m_liveNodeWindows->CountItems() > 0) {
184 			live_node_window *entry = static_cast<live_node_window *>
185 									  (m_liveNodeWindows->ItemAt(0));
186 			if (entry && entry->window) {
187 				remove_observer(this, entry->ref);
188 				BMessenger messenger(0, entry->window);
189 				messenger.SendMessage(B_QUIT_REQUESTED);
190 			}
191 			m_liveNodeWindows->RemoveItem(reinterpret_cast<void *>(entry));
192 			delete entry;
193 		}
194 		delete m_liveNodeWindows;
195 		m_liveNodeWindows = 0;
196 	}
197 
198 	if (m_dormantNodeWindows) {
199 		while (m_dormantNodeWindows->CountItems() > 0) {
200 			dormant_node_window *entry = static_cast<dormant_node_window *>
201 										 (m_dormantNodeWindows->ItemAt(0));
202 			if (entry && entry->window) {
203 				BMessenger messenger(0, entry->window);
204 				messenger.SendMessage(B_QUIT_REQUESTED);
205 			}
206 			m_dormantNodeWindows->RemoveItem(reinterpret_cast<void *>(entry));
207 			delete entry;
208 		}
209 		delete m_dormantNodeWindows;
210 		m_dormantNodeWindows = 0;
211 	}
212 
213 	if (m_connectionWindows) {
214 		while (m_connectionWindows->CountItems() > 0) {
215 			connection_window *entry = static_cast<connection_window *>
216 									   (m_connectionWindows->ItemAt(0));
217 			if (entry && entry->window) {
218 				BMessenger messenger(0, entry->window);
219 				messenger.SendMessage(B_QUIT_REQUESTED);
220 			}
221 			m_connectionWindows->RemoveItem(reinterpret_cast<void *>(entry));
222 			delete entry;
223 		}
224 		delete m_connectionWindows;
225 		m_connectionWindows = 0;
226 	}
227 
228 	if (m_inputWindows) {
229 		while (m_inputWindows->CountItems() > 0) {
230 			input_window *entry = static_cast<input_window *>
231 								  (m_inputWindows->ItemAt(0));
232 			if (entry && entry->window) {
233 				BMessenger messenger(0, entry->window);
234 				messenger.SendMessage(B_QUIT_REQUESTED);
235 			}
236 			m_inputWindows->RemoveItem(reinterpret_cast<void *>(entry));
237 			delete entry;
238 		}
239 		delete m_inputWindows;
240 		m_inputWindows = 0;
241 	}
242 
243 	if (m_outputWindows) {
244 		while (m_outputWindows->CountItems() > 0) {
245 			output_window *entry = static_cast<output_window *>
246 								   (m_outputWindows->ItemAt(0));
247 			if (entry && entry->window) {
248 				BMessenger messenger(0, entry->window);
249 				messenger.SendMessage(B_QUIT_REQUESTED);
250 			}
251 			m_outputWindows->RemoveItem(reinterpret_cast<void *>(entry));
252 			delete entry;
253 		}
254 		delete m_outputWindows;
255 		m_outputWindows = 0;
256 	}
257 }
258 
259 // -------------------------------------------------------- //
260 // *** singleton access
261 // -------------------------------------------------------- //
262 
263 /*static*/
264 InfoWindowManager *InfoWindowManager::Instance() {
265 	D_ACCESS(("InfoWindowManager::Instance()\n"));
266 
267 	if (!s_instance) {
268 		D_ACCESS((" -> create instance\n"));
269 		s_instance = new InfoWindowManager();
270 	}
271 
272 	return s_instance;
273 }
274 
275 /* static */
276 void InfoWindowManager::shutDown() {
277 	D_WINDOW(("InfoWindowManager::shutDown()\n"));
278 
279 	if (s_instance) {
280 		s_instance->Lock();
281 		s_instance->Quit();
282 		s_instance = 0;
283 	}
284 }
285 
286 // -------------------------------------------------------- //
287 // *** operations
288 // -------------------------------------------------------- //
289 
290 status_t InfoWindowManager::openWindowFor(
291 	const NodeRef *ref) {
292 	D_WINDOW(("InfoWindowManager::openWindowFor(live_node)\n"));
293 
294 	// make absolutely sure we're locked
295 	if (!IsLocked()) {
296 		debugger("The looper must be locked !");
297 	}
298 
299 	// make sure the ref is valid
300 	if (!ref) {
301 		return B_ERROR;
302 	}
303 
304 	BWindow *window = 0;
305 	if (_findWindowFor(ref->id(), &window)) {
306 		// window for this node already exists, activate it
307 		window->SetWorkspaces(B_CURRENT_WORKSPACE);
308 		window->Activate();
309 		return B_OK;
310 	}
311 
312 	BRect frame = InfoView::M_DEFAULT_FRAME;
313 	frame.OffsetTo(m_nextWindowPosition);
314 	m_nextWindowPosition += M_DEFAULT_OFFSET;
315 	window = new InfoWindow(frame);
316 
317 	if (_addWindowFor(ref, window)) {
318 		// find the correct InfoView sub-class
319 		BMediaRoster *roster = BMediaRoster::CurrentRoster();
320 		dormant_node_info dormantNodeInfo;
321 		if (ref->kind() & B_FILE_INTERFACE)
322 		{
323 			window->AddChild(new FileNodeInfoView(ref));
324 		}
325 		else if (roster->GetDormantNodeFor(ref->node(), &dormantNodeInfo) != B_OK) {
326 			port_info portInfo;
327 			app_info appInfo;
328 			if ((get_port_info(ref->node().port, &portInfo) == B_OK)
329 			 && (be_roster->GetRunningAppInfo(portInfo.team, &appInfo) == B_OK)) {
330 				app_info thisAppInfo;
331 				if ((be_app->GetAppInfo(&thisAppInfo) != B_OK)
332 				 || ((strcmp(appInfo.signature, thisAppInfo.signature) != 0)
333 				 && (strcmp(appInfo.signature, addon_host::g_appSignature) != 0))) {
334 					window->AddChild(new AppNodeInfoView(ref));
335 				}
336 				else {
337 					window->AddChild(new LiveNodeInfoView(ref));
338 				}
339 			}
340 			else {
341 				window->AddChild(new LiveNodeInfoView(ref));
342 			}
343 		}
344 		else {
345 			window->AddChild(new LiveNodeInfoView(ref));
346 		}
347 		// display the window
348 		window->Show();
349 		return B_OK;
350 	}
351 
352 	// failed
353 	delete window;
354 	return B_ERROR;
355 }
356 
357 status_t InfoWindowManager::openWindowFor(
358 	const dormant_node_info &info) {
359 	D_WINDOW(("InfoWindowManager::openWindowFor(dormant_node)\n"));
360 
361 	// make absolutely sure we're locked
362 	if (!IsLocked()) {
363 		debugger("The looper must be locked !");
364 	}
365 
366 	BWindow *window = 0;
367 	if (_findWindowFor(info, &window)) {
368 		// window for this node already exists, activate it
369 		window->SetWorkspaces(B_CURRENT_WORKSPACE);
370 		window->Activate();
371 		return B_OK;
372 	}
373 
374 	BRect frame = InfoView::M_DEFAULT_FRAME;
375 	frame.OffsetTo(m_nextWindowPosition);
376 	m_nextWindowPosition += M_DEFAULT_OFFSET;
377 	window = new InfoWindow(frame);
378 
379 	if (_addWindowFor(info, window)) {
380 		window->AddChild(new DormantNodeInfoView(info));
381 		window->Show();
382 		return B_OK;
383 	}
384 
385 	// failed
386 	delete window;
387 	return B_ERROR;
388 }
389 
390 status_t InfoWindowManager::openWindowFor(
391 	const Connection &connection) {
392 	D_WINDOW(("InfoWindowManager::openWindowFor(connection)\n"));
393 
394 	// make absolutely sure we're locked
395 	if (!IsLocked()) {
396 		debugger("The looper must be locked !");
397 	}
398 
399 	BWindow *window = 0;
400 	if (_findWindowFor(connection.source(), connection.destination(), &window)) {
401 		// window for this node already exists, activate it
402 		window->SetWorkspaces(B_CURRENT_WORKSPACE);
403 		window->Activate();
404 		return B_OK;
405 	}
406 
407 	BRect frame = InfoView::M_DEFAULT_FRAME;
408 	frame.OffsetTo(m_nextWindowPosition);
409 	m_nextWindowPosition += M_DEFAULT_OFFSET;
410 	window = new InfoWindow(frame);
411 
412 	if (_addWindowFor(connection, window)) {
413 		window->AddChild(new ConnectionInfoView(connection));
414 		window->Show();
415 		return B_OK;
416 	}
417 
418 	// failed
419 	delete window;
420 	return B_ERROR;
421 }
422 
423 status_t InfoWindowManager::openWindowFor(
424 	const media_input &input) {
425 	D_WINDOW(("InfoWindowManager::openWindowFor(input)\n"));
426 
427 	// make absolutely sure we're locked
428 	if (!IsLocked()) {
429 		debugger("The looper must be locked !");
430 	}
431 
432 	BWindow *window = 0;
433 	if (_findWindowFor(input.destination, &window)) {
434 		// window for this node already exists, activate it
435 		window->SetWorkspaces(B_CURRENT_WORKSPACE);
436 		window->Activate();
437 		return B_OK;
438 	}
439 
440 	BRect frame = InfoView::M_DEFAULT_FRAME;
441 	frame.OffsetTo(m_nextWindowPosition);
442 	m_nextWindowPosition += M_DEFAULT_OFFSET;
443 	window = new InfoWindow(frame);
444 
445 	if (_addWindowFor(input, window)) {
446 		window->AddChild(new EndPointInfoView(input));
447 		window->Show();
448 		return B_OK;
449 	}
450 
451 	// failed
452 	delete window;
453 	return B_ERROR;
454 }
455 
456 status_t InfoWindowManager::openWindowFor(
457 	const media_output &output) {
458 	D_WINDOW(("InfoWindowManager::openWindowFor(output)\n"));
459 
460 	// make absolutely sure we're locked
461 	if (!IsLocked()) {
462 		debugger("The looper must be locked !");
463 	}
464 
465 	BWindow *window = 0;
466 	if (_findWindowFor(output.source, &window)) {
467 		// window for this node already exists, activate it
468 		window->SetWorkspaces(B_CURRENT_WORKSPACE);
469 		window->Activate();
470 		return B_OK;
471 	}
472 
473 	BRect frame = InfoView::M_DEFAULT_FRAME;
474 	frame.OffsetTo(m_nextWindowPosition);
475 	m_nextWindowPosition += M_DEFAULT_OFFSET;
476 	window = new BWindow(frame, "", B_DOCUMENT_WINDOW, 0);
477 
478 	if (_addWindowFor(output, window)) {
479 		window->AddChild(new EndPointInfoView(output));
480 		window->Show();
481 		return B_OK;
482 	}
483 
484 	// failed
485 	delete window;
486 	return B_ERROR;
487 }
488 
489 // -------------------------------------------------------- //
490 // *** BLooper impl
491 // -------------------------------------------------------- //
492 
493 void InfoWindowManager::MessageReceived(
494 	BMessage *message) {
495 	D_MESSAGE(("InfoWindowManager::MessageReceived()\n"));
496 
497 	switch (message->what) {
498 		case M_LIVE_NODE_WINDOW_CLOSED: {
499 			D_MESSAGE((" -> M_LIVE_NODE_WINDOW_CLOSED\n"));
500 			int32 nodeID;
501 			if (message->FindInt32("nodeID", &nodeID) != B_OK) {
502 				return;
503 			}
504 			_removeWindowFor(nodeID);
505 			break;
506 		}
507 		case M_DORMANT_NODE_WINDOW_CLOSED: {
508 			D_MESSAGE((" -> M_DORMANT_NODE_WINDOW_CLOSED\n"));
509 			dormant_node_info info;
510 			if (message->FindInt32("addOnID", &info.addon) != B_OK) {
511 				return;
512 			}
513 			if (message->FindInt32("flavorID", &info.flavor_id) != B_OK) {
514 				return;
515 			}
516 			_removeWindowFor(info);
517 			break;
518 		}
519 		case M_CONNECTION_WINDOW_CLOSED: {
520 			D_MESSAGE((" -> M_CONNECTION_WINDOW_CLOSED\n"));
521 			media_source source;
522 			if (message->FindInt32("source_port", &source.port) != B_OK) {
523 				return;
524 			}
525 			if (message->FindInt32("source_id", &source.id) != B_OK) {
526 				return;
527 			}
528 			media_destination destination;
529 			if (message->FindInt32("destination_port", &destination.port) != B_OK) {
530 				return;
531 			}
532 			if (message->FindInt32("destination_id", &destination.id) != B_OK) {
533 				return;
534 			}
535 			_removeWindowFor(source, destination);
536 			break;
537 		}
538 		case M_INPUT_WINDOW_CLOSED: {
539 			D_MESSAGE((" -> M_INPUT_WINDOW_CLOSED\n"));
540 			media_destination destination;
541 			if (message->FindInt32("destination_port", &destination.port) != B_OK) {
542 				return;
543 			}
544 			if (message->FindInt32("destination_id", &destination.id) != B_OK) {
545 				return;
546 			}
547 			_removeWindowFor(destination);
548 			break;
549 		}
550 		case M_OUTPUT_WINDOW_CLOSED: {
551 			D_MESSAGE((" -> M_OUTPUT_WINDOW_CLOSED\n"));
552 			media_source source;
553 			if (message->FindInt32("source_port", &source.port) != B_OK) {
554 				return;
555 			}
556 			if (message->FindInt32("source_id", &source.id) != B_OK) {
557 				return;
558 			}
559 			_removeWindowFor(source);
560 			break;
561 		}
562 		case NodeRef::M_RELEASED: {
563 			D_MESSAGE((" -> NodeRef::M_RELEASED\n"));
564 			int32 nodeID;
565 			if (message->FindInt32("nodeID", &nodeID) != B_OK) {
566 				return;
567 			}
568 			BWindow *window;
569 			if (_findWindowFor(nodeID, &window)) {
570 				window->Lock();
571 				window->Quit();
572 				_removeWindowFor(nodeID);
573 			}
574 			break;
575 		}
576 		case B_MEDIA_CONNECTION_BROKEN: {
577 			D_MESSAGE((" -> B_MEDIA_CONNECTION_BROKEN\n"));
578 			const void *data;
579 			ssize_t dataSize;
580 			if (message->FindData("source", B_RAW_TYPE, &data, &dataSize) != B_OK) {
581 				return;
582 			}
583 			const media_source source = *reinterpret_cast<const media_source *>(data);
584 			if (message->FindData("destination", B_RAW_TYPE, &data, &dataSize) != B_OK) {
585 				return;
586 			}
587 			const media_destination destination = *reinterpret_cast<const media_destination *>(data);
588 			BWindow *window;
589 			if (_findWindowFor(source, destination, &window)) {
590 				window->Lock();
591 				window->Quit();
592 				_removeWindowFor(source, destination);
593 			}
594 			break;
595 		}
596 		default: {
597 			BLooper::MessageReceived(message);
598 		}
599 	}
600 }
601 
602 // -------------------------------------------------------- //
603 // *** internal operations
604 // -------------------------------------------------------- //
605 
606 bool InfoWindowManager::_addWindowFor(
607 	const NodeRef *ref,
608 	BWindow *window) {
609 	D_INTERNAL(("InfoWindowManager::_addWindowFor(live_node)\n"));
610 
611 	if (!m_liveNodeWindows) {
612 		m_liveNodeWindows = new BList();
613 	}
614 
615 	live_node_window *entry = new live_node_window(ref, window);
616 	if (m_liveNodeWindows->AddItem(reinterpret_cast<void *>(entry))) {
617 		add_observer(this, entry->ref);
618 		return true;
619 	}
620 
621 	return false;
622 }
623 
624 bool InfoWindowManager::_findWindowFor(
625 	int32 nodeID,
626 	BWindow **outWindow) {
627 	D_INTERNAL(("InfoWindowManager::_findWindowFor(live_node)\n"));
628 
629 	if (!m_liveNodeWindows) {
630 		return false;
631 	}
632 
633 	for (int32 i = 0; i < m_liveNodeWindows->CountItems(); i++) {
634 		live_node_window *entry = static_cast<live_node_window *>
635 								  (m_liveNodeWindows->ItemAt(i));
636 		if (entry->ref->id() == nodeID) {
637 			*outWindow = entry->window;
638 			return true;
639 		}
640 	}
641 
642 	return false;
643 }
644 
645 void InfoWindowManager::_removeWindowFor(
646 	int32 nodeID) {
647 	D_INTERNAL(("InfoWindowManager::_removeWindowFor(live_node)\n"));
648 
649 	if (!m_liveNodeWindows) {
650 		return;
651 	}
652 
653 	for (int32 i = 0; i < m_liveNodeWindows->CountItems(); i++) {
654 		live_node_window *entry = static_cast<live_node_window *>
655 								  (m_liveNodeWindows->ItemAt(i));
656 		if (entry->ref->id() == nodeID) {
657 			m_liveNodeWindows->RemoveItem(reinterpret_cast<void *>(entry));
658 			remove_observer(this, entry->ref);
659 			delete entry;
660 		}
661 	}
662 
663 	if (m_liveNodeWindows->CountItems() <= 0) {
664 		delete m_liveNodeWindows;
665 		m_liveNodeWindows = 0;
666 	}
667 }
668 
669 bool InfoWindowManager::_addWindowFor(
670 	const dormant_node_info &info,
671 	BWindow *window) {
672 	D_INTERNAL(("InfoWindowManager::_addWindowFor(dormant_node)\n"));
673 
674 	if (!m_dormantNodeWindows) {
675 		m_dormantNodeWindows = new BList();
676 	}
677 
678 	dormant_node_window *entry = new dormant_node_window(info, window);
679 	return m_dormantNodeWindows->AddItem(reinterpret_cast<void *>(entry));
680 }
681 
682 bool InfoWindowManager::_findWindowFor(
683 	const dormant_node_info &info,
684 	BWindow **outWindow) {
685 	D_INTERNAL(("InfoWindowManager::_findWindowFor(dormant_node)\n"));
686 
687 	if (!m_dormantNodeWindows) {
688 		return false;
689 	}
690 
691 	for (int32 i = 0; i < m_dormantNodeWindows->CountItems(); i++) {
692 		dormant_node_window *entry = static_cast<dormant_node_window *>
693 									 (m_dormantNodeWindows->ItemAt(i));
694 		if ((entry->info.addon == info.addon)
695 		 && (entry->info.flavor_id == info.flavor_id)) {
696 			*outWindow = entry->window;
697 			return true;
698 		}
699 	}
700 
701 	return false;
702 }
703 
704 void InfoWindowManager::_removeWindowFor(
705 	const dormant_node_info &info) {
706 	D_INTERNAL(("InfoWindowManager::_removeWindowFor(dormant_node)\n"));
707 
708 	if (!m_dormantNodeWindows) {
709 		return;
710 	}
711 
712 	for (int32 i = 0; i < m_dormantNodeWindows->CountItems(); i++) {
713 		dormant_node_window *entry = static_cast<dormant_node_window *>
714 									 (m_dormantNodeWindows->ItemAt(i));
715 		if ((entry->info.addon == info.addon)
716 		 && (entry->info.flavor_id == info.flavor_id)) {
717 			m_dormantNodeWindows->RemoveItem(reinterpret_cast<void *>(entry));
718 			delete entry;
719 		}
720 	}
721 
722 	if (m_dormantNodeWindows->CountItems() >= 0) {
723 		delete m_dormantNodeWindows;
724 		m_dormantNodeWindows = 0;
725 	}
726 }
727 
728 bool InfoWindowManager::_addWindowFor(
729 	const Connection &connection,
730 	BWindow *window) {
731 	D_INTERNAL(("InfoWindowManager::_addWindowFor(connection)\n"));
732 
733 	if (!m_connectionWindows) {
734 		m_connectionWindows = new BList();
735 	}
736 
737 	connection_window *entry = new connection_window(connection.source(),
738 													 connection.destination(),
739 													 window);
740 	return m_connectionWindows->AddItem(reinterpret_cast<void *>(entry));
741 }
742 
743 bool InfoWindowManager::_findWindowFor(
744 	const media_source &source,
745 	const media_destination &destination,
746 	BWindow **outWindow) {
747 	D_INTERNAL(("InfoWindowManager::_findWindowFor(connection)\n"));
748 
749 	if (!m_connectionWindows) {
750 		return false;
751 	}
752 
753 	for (int32 i = 0; i < m_connectionWindows->CountItems(); i++) {
754 		connection_window *entry = static_cast<connection_window *>
755 								   (m_connectionWindows->ItemAt(i));
756 		if ((entry->source == source)
757 		 && (entry->destination == destination)) {
758 			*outWindow = entry->window;
759 			return true;
760 		}
761 	}
762 
763 	return false;
764 }
765 
766 void InfoWindowManager::_removeWindowFor(
767 	const media_source &source,
768 	const media_destination &destination) {
769 	D_INTERNAL(("InfoWindowManager::_removeWindowFor(connection)\n"));
770 
771 	if (!m_connectionWindows) {
772 		return;
773 	}
774 
775 	for (int32 i = 0; i < m_connectionWindows->CountItems(); i++) {
776 		connection_window *entry = static_cast<connection_window *>
777 								   (m_connectionWindows->ItemAt(i));
778 		if ((entry->source == source)
779 		 && (entry->destination == destination)) {
780 			m_connectionWindows->RemoveItem(reinterpret_cast<void *>(entry));
781 			delete entry;
782 		}
783 	}
784 
785 	if (m_connectionWindows->CountItems() >= 0) {
786 		delete m_connectionWindows;
787 		m_connectionWindows = 0;
788 	}
789 }
790 
791 bool InfoWindowManager::_addWindowFor(
792 	const media_input &input,
793 	BWindow *window) {
794 	D_INTERNAL(("InfoWindowManager::_addWindowFor(input)\n"));
795 
796 	if (!m_inputWindows) {
797 		m_inputWindows = new BList();
798 	}
799 
800 	input_window *entry = new input_window(input.destination, window);
801 	return m_inputWindows->AddItem(reinterpret_cast<void *>(entry));
802 }
803 
804 bool InfoWindowManager::_findWindowFor(
805 	const media_destination &destination,
806 	BWindow **outWindow) {
807 	D_INTERNAL(("InfoWindowManager::_findWindowFor(input)\n"));
808 
809 	if (!m_inputWindows) {
810 		return false;
811 	}
812 
813 	for (int32 i = 0; i < m_inputWindows->CountItems(); i++) {
814 		input_window *entry = static_cast<input_window *>
815 							  (m_inputWindows->ItemAt(i));
816 		if (entry->destination == destination) {
817 			*outWindow = entry->window;
818 			return true;
819 		}
820 	}
821 
822 	return false;
823 }
824 
825 void InfoWindowManager::_removeWindowFor(
826 	const media_destination &destination) {
827 	D_INTERNAL(("InfoWindowManager::_removeWindowFor(input)\n"));
828 
829 	if (!m_inputWindows) {
830 		return;
831 	}
832 
833 	for (int32 i = 0; i < m_inputWindows->CountItems(); i++) {
834 		input_window *entry = static_cast<input_window *>
835 							  (m_inputWindows->ItemAt(i));
836 		if (entry->destination == destination) {
837 			m_inputWindows->RemoveItem(reinterpret_cast<void *>(entry));
838 			delete entry;
839 		}
840 	}
841 
842 	if (m_inputWindows->CountItems() >= 0) {
843 		delete m_inputWindows;
844 		m_inputWindows = 0;
845 	}
846 }
847 
848 bool InfoWindowManager::_addWindowFor(
849 	const media_output &output,
850 	BWindow *window) {
851 	D_INTERNAL(("InfoWindowManager::_addWindowFor(output)\n"));
852 
853 	if (!m_outputWindows) {
854 		m_outputWindows = new BList();
855 	}
856 
857 	output_window *entry = new output_window(output.source, window);
858 	return m_outputWindows->AddItem(reinterpret_cast<void *>(entry));
859 }
860 
861 bool InfoWindowManager::_findWindowFor(
862 	const media_source &source,
863 	BWindow **outWindow) {
864 	D_INTERNAL(("InfoWindowManager::_findWindowFor(output)\n"));
865 
866 	if (!m_outputWindows) {
867 		return false;
868 	}
869 
870 	for (int32 i = 0; i < m_outputWindows->CountItems(); i++) {
871 		output_window *entry = static_cast<output_window *>
872 							  (m_outputWindows->ItemAt(i));
873 		if (entry->source == source) {
874 			*outWindow = entry->window;
875 			return true;
876 		}
877 	}
878 
879 	return false;
880 }
881 
882 void InfoWindowManager::_removeWindowFor(
883 	const media_source &source) {
884 	D_INTERNAL(("InfoWindowManager::_removeWindowFor(output)\n"));
885 
886 	if (!m_outputWindows) {
887 		return;
888 	}
889 
890 	for (int32 i = 0; i < m_outputWindows->CountItems(); i++) {
891 		output_window *entry = static_cast<output_window *>
892 							  (m_outputWindows->ItemAt(i));
893 		if (entry->source == source) {
894 			m_outputWindows->RemoveItem(reinterpret_cast<void *>(entry));
895 			delete entry;
896 		}
897 	}
898 
899 	if (m_outputWindows->CountItems() >= 0) {
900 		delete m_outputWindows;
901 		m_outputWindows = 0;
902 	}
903 }
904 
905 // END -- InfoWindowManager.cpp --
906