xref: /haiku/src/preferences/media/MediaWindow.cpp (revision e0ef64750f3169cd634bb2f7a001e22488b05231)
1 /*
2  * Copyright (c) 2003-2005, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Sikosis, Jérôme Duval
7  */
8 
9 
10 #include <stdio.h>
11 
12 #include <Alert.h>
13 #include <Application.h>
14 #include <Autolock.h>
15 #include <Bitmap.h>
16 #include <Button.h>
17 #include <Catalog.h>
18 #include <Debug.h>
19 #include <Deskbar.h>
20 #include <GroupView.h>
21 #include <Locale.h>
22 #include <MediaTheme.h>
23 #include <MediaRoster.h>
24 #include <Roster.h>
25 #include <Screen.h>
26 #include <ScrollView.h>
27 #include <SpaceLayoutItem.h>
28 #include <StorageKit.h>
29 #include <String.h>
30 #include <TextView.h>
31 #include "MediaWindow.h"
32 
33 // Images
34 #include "iconfile.h"
35 
36 
37 #undef B_TRANSLATE_CONTEXT
38 #define B_TRANSLATE_CONTEXT "Media Window"
39 
40 
41 const uint32 ML_SELECTED_NODE = 'MlSN';
42 const uint32 ML_INIT_MEDIA = 'MlIM';
43 
44 // MediaWindow - Constructor
45 MediaWindow::MediaWindow(BRect frame)
46 : BWindow (frame, B_TRANSLATE("Media"), B_TITLED_WINDOW,
47 	B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
48 	fCurrentNode(NULL),
49 	fParamWeb(NULL),
50 	fAlert(NULL),
51 	fInitCheck(B_OK)
52 {
53 	InitWindow();
54 }
55 
56 
57 status_t
58 MediaWindow::InitCheck()
59 {
60 	return fInitCheck;
61 }
62 
63 
64 // MediaWindow - Destructor
65 MediaWindow::~MediaWindow()
66 {
67 	for (int i = 0; i<fAudioOutputs.CountItems(); i++)
68 		delete static_cast<dormant_node_info *>(fAudioOutputs.ItemAt(i));
69 	for (int i = 0; i<fAudioInputs.CountItems(); i++)
70 		delete static_cast<dormant_node_info *>(fAudioInputs.ItemAt(i));
71 	for (int i = 0; i<fVideoOutputs.CountItems(); i++)
72 		delete static_cast<dormant_node_info *>(fVideoOutputs.ItemAt(i));
73 	for (int i = 0; i<fVideoInputs.CountItems(); i++)
74 		delete static_cast<dormant_node_info *>(fVideoInputs.ItemAt(i));
75 
76 	BMediaRoster *roster = BMediaRoster::Roster();
77 	if (roster && fCurrentNode)
78 		roster->ReleaseNode(*fCurrentNode);
79 
80 	char buffer[512];
81 	BRect rect = Frame();
82 	PRINT_OBJECT(rect);
83 	sprintf(buffer, "# MediaPrefs Settings\n rect = %i,%i,%i,%i\n",
84 		int(rect.left), int(rect.top), int(rect.right), int(rect.bottom));
85 
86 	BPath path;
87 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
88 		path.Append(SETTINGS_FILE);
89 		BFile file(path.Path(), B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE);
90 		if (file.InitCheck()==B_OK) {
91 			file.Write(buffer, strlen(buffer));
92 		}
93 	}
94 }
95 
96 
97 void
98 MediaWindow::FindNodes(media_type type, uint64 kind, BList &list)
99 {
100 	dormant_node_info node_info[64];
101 	int32 node_info_count = 64;
102 	media_format format;
103 	media_format *format1 = NULL, *format2 = NULL;
104 	BMediaRoster *roster = BMediaRoster::Roster();
105 	format.type = type;
106 
107 	if (kind & B_PHYSICAL_OUTPUT)
108 		format1 = &format;
109 	else if (kind & B_PHYSICAL_INPUT)
110 		format2 = &format;
111 	else
112 		return;
113 
114 	if (roster->GetDormantNodes(node_info, &node_info_count, format1, format2,
115 			NULL, kind)!=B_OK) {
116 		fprintf(stderr, "error\n");
117 		return;
118 	}
119 
120 	for (int32 i = 0; i<node_info_count; i++) {
121 		PRINT(("node : %s, media_addon %i, flavor_id %i\n",
122 			node_info[i].name, node_info[i].addon, node_info[i].flavor_id));
123 		dormant_node_info *info = new dormant_node_info();
124 		strcpy(info->name, node_info[i].name);
125 		info->flavor_id = node_info[i].flavor_id;
126 		info->addon = node_info[i].addon;
127 		list.AddItem(info);
128 	}
129 }
130 
131 
132 MediaListItem *
133 MediaWindow::FindMediaListItem(dormant_node_info *info)
134 {
135 	for (int32 j = 0; j<fListView->CountItems(); j++) {
136 		MediaListItem *item
137 			= static_cast<MediaListItem *>(fListView->ItemAt(j));
138 		if (item->fInfo && item->fInfo->addon == info->addon
139 				&& item->fInfo->flavor_id == info->flavor_id) {
140 			return item;
141 			break;
142 		}
143 	}
144 	return NULL;
145 }
146 
147 
148 void
149 MediaWindow::AddNodes(BList &list, bool isVideo)
150 {
151 	for (int32 i = 0; i<list.CountItems(); i++) {
152 		dormant_node_info *info
153 			= static_cast<dormant_node_info *>(list.ItemAt(i));
154 		if (!FindMediaListItem(info))
155 			fListView->AddItem(new MediaListItem(info, 1, isVideo, &fIcons));
156 	}
157 }
158 
159 
160 // MediaWindow::InitWindow -- Initialization Commands here
161 void
162 MediaWindow::InitWindow(void)
163 {
164 	// Bitmaps
165 	BRect iconRect(0, 0, 15, 15);
166 	BBitmap *icon = new BBitmap(iconRect, B_CMAP8);
167 	icon->SetBits(kDevicesBits, kDevicesWidth * kDevicesHeight, 0,
168 			kDevicesColorSpace);
169 	fIcons.AddItem(icon);
170 	icon = new BBitmap(iconRect, B_CMAP8);
171 	icon->SetBits(kMixerBits, kMixerWidth * kMixerHeight, 0,
172 			kMixerColorSpace);
173 	fIcons.AddItem(icon);
174 	icon = new BBitmap(iconRect, B_CMAP8);
175 	icon->SetBits(kMicBits, kMicWidth * kMicHeight, 0, kMicColorSpace);
176 	fIcons.AddItem(icon);
177 	icon = new BBitmap(iconRect, B_CMAP8);
178 	icon->SetBits(kSpeakerBits, kSpeakerWidth * kSpeakerHeight, 0,
179 			kSpeakerColorSpace);
180 	fIcons.AddItem(icon);
181 	icon = new BBitmap(iconRect, B_CMAP8);
182 	icon->SetBits(kCamBits, kCamWidth * kCamHeight, 0, kCamColorSpace);
183 	fIcons.AddItem(icon);
184 	icon = new BBitmap(iconRect, B_CMAP8);
185 	icon->SetBits(kTVBits, kTVWidth * kTVHeight, 0, kTVColorSpace);
186 	fIcons.AddItem(icon);
187 
188 	const float scrollWidth = 9 * be_plain_font->Size() + 30;
189 
190 	fListView = new BListView("media_list_view");
191 	fListView->SetSelectionMessage(new BMessage(ML_SELECTED_NODE));
192 
193 	// Add ScrollView to Media Menu
194 	BScrollView *scrollView = new BScrollView("listscroller",
195 		fListView, 0, false, false, B_FANCY_BORDER);
196 	scrollView->SetExplicitMinSize(BSize(scrollWidth, B_SIZE_UNSET));
197 	scrollView->SetExplicitMaxSize(BSize(scrollWidth, B_SIZE_UNSET));
198 
199 	// Create the Views
200 	fBox = new BBox("background", B_WILL_DRAW | B_FRAME_EVENTS,
201 		B_PLAIN_BORDER);
202 	SetLayout(new BGroupLayout(B_HORIZONTAL));
203 	GetLayout()->AddView(fBox);
204 
205 	// StringViews
206 	rgb_color titleFontColor = { 0, 0, 0, 0 };
207 	fTitleView = new BStringView("AudioSettings",
208 		B_TRANSLATE("Audio settings"), B_WILL_DRAW);
209 	fTitleView->SetFont(be_bold_font);
210 	fTitleView->SetHighColor(titleFontColor);
211 
212 	fContentView = new BBox("contentView", B_WILL_DRAW | B_FRAME_EVENTS,
213 		B_NO_BORDER);
214 
215 	fAudioView = new SettingsView(false);
216 	fVideoView = new SettingsView(true);
217 
218 	fBar = new BarView();
219 	BGroupView* titleGroupView = new BGroupView(B_HORIZONTAL);
220 	titleGroupView->GroupLayout()->AddView(fTitleView);
221 	titleGroupView->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
222 
223 	// Layout all views
224 	BGroupView* rightView = new BGroupView(B_VERTICAL, 5);
225 	rightView->GroupLayout()->SetInsets(14, 0, 0, 0);
226 	rightView->GroupLayout()->AddView(titleGroupView);
227 	rightView->GroupLayout()->AddView(fBar, 0);
228 	rightView->GroupLayout()->AddView(fContentView);
229 
230 	BGroupLayout* rootLayout = new BGroupLayout(B_HORIZONTAL);
231 	rootLayout->SetInsets(14, 14, 14, 14);
232 	fBox->SetLayout(rootLayout);
233 
234 	rootLayout->AddView(scrollView);
235 
236 	rootLayout->AddView(rightView);
237 
238 	// Start the window
239 	fInitCheck = InitMedia(true);
240 	if (fInitCheck != B_OK) {
241 		PostMessage(B_QUIT_REQUESTED);
242 	} else {
243 		if (IsHidden())
244 			Show();
245 	}
246 }
247 
248 
249 // #pragma mark -
250 
251 
252 status_t
253 MediaWindow::InitMedia(bool first)
254 {
255 	status_t err = B_OK;
256 	BMediaRoster *roster = BMediaRoster::Roster(&err);
257 
258 	if (first && err != B_OK) {
259 		BAlert *alert = new BAlert("start_media_server",
260 			B_TRANSLATE("Could not connect to the media server.\n"
261 			"Would you like to start it ?"),
262 			B_TRANSLATE("Quit"),
263 			B_TRANSLATE("Start media server"), NULL,
264 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
265 		if (alert->Go()==0)
266 			return B_ERROR;
267 
268 		fAlert = new MediaAlert(BRect(0, 0, 300, 60),
269 			"restart_alert", B_TRANSLATE(
270 				"Restarting media services\nStarting media server"
271 				B_UTF8_ELLIPSIS "\n"));
272 		fAlert->Show();
273 
274 		Show();
275 
276 		launch_media_server();
277 	}
278 
279 	Lock();
280 
281 	bool isVideoSelected = true;
282 	if (!first && fListView->ItemAt(0) && fListView->ItemAt(0)->IsSelected())
283 		isVideoSelected = false;
284 
285 	if ((!first || (first && err) ) && fAlert) {
286 		BAutolock locker(fAlert);
287 		if (locker.IsLocked())
288 			fAlert->TextView()->SetText(
289 				B_TRANSLATE("Ready for use" B_UTF8_ELLIPSIS));
290 	}
291 
292 	void *listItem;
293 	while ((listItem = fListView->RemoveItem((int32)0)))
294 		delete static_cast<MediaListItem *>(listItem);
295 	while ((listItem = fAudioOutputs.RemoveItem((int32)0)))
296 		delete static_cast<dormant_node_info *>(listItem);
297 	while ((listItem = fAudioInputs.RemoveItem((int32)0)))
298 		delete static_cast<dormant_node_info *>(listItem);
299 	while ((listItem = fVideoOutputs.RemoveItem((int32)0)))
300 		delete static_cast<dormant_node_info *>(listItem);
301 	while ((listItem = fVideoInputs.RemoveItem((int32)0)))
302 		delete static_cast<dormant_node_info *>(listItem);
303 
304 	MediaListItem *item, *mixer, *audio, *video;
305 
306 	// Grab Media Info
307 	FindNodes(B_MEDIA_RAW_AUDIO, B_PHYSICAL_OUTPUT, fAudioOutputs);
308 	FindNodes(B_MEDIA_RAW_AUDIO, B_PHYSICAL_INPUT, fAudioInputs);
309 	FindNodes(B_MEDIA_ENCODED_AUDIO, B_PHYSICAL_OUTPUT, fAudioOutputs);
310 	FindNodes(B_MEDIA_ENCODED_AUDIO, B_PHYSICAL_INPUT, fAudioInputs);
311 	FindNodes(B_MEDIA_RAW_VIDEO, B_PHYSICAL_OUTPUT, fVideoOutputs);
312 	FindNodes(B_MEDIA_RAW_VIDEO, B_PHYSICAL_INPUT, fVideoInputs);
313 	FindNodes(B_MEDIA_ENCODED_VIDEO, B_PHYSICAL_OUTPUT, fVideoOutputs);
314 	FindNodes(B_MEDIA_ENCODED_VIDEO, B_PHYSICAL_INPUT, fVideoInputs);
315 
316 	// Add video nodes first. They might have an additional audio
317 	// output or input, but still should be listed as video node.
318 	AddNodes(fVideoOutputs, true);
319 	AddNodes(fVideoInputs, true);
320 	AddNodes(fAudioOutputs, false);
321 	AddNodes(fAudioInputs, false);
322 
323 	fAudioView->AddNodes(fAudioOutputs, false);
324 	fAudioView->AddNodes(fAudioInputs, true);
325 	fVideoView->AddNodes(fVideoOutputs, false);
326 	fVideoView->AddNodes(fVideoInputs, true);
327 
328 	fListView->AddItem(audio = new MediaListItem("Audio settings", 0, false, &fIcons));
329 	fListView->AddItem(video = new MediaListItem("Video settings", 0, true, &fIcons));
330 
331 	fListView->AddItem(mixer = new MediaListItem("Audio mixer", 1, false, &fIcons));
332 	mixer->SetAudioMixer(true);
333 
334 	fListView->SortItems(&MediaListItem::Compare);
335 
336 	media_node default_node;
337 	dormant_node_info node_info;
338 	int32 outputID;
339 	BString outputName;
340 
341 	if (roster->GetAudioInput(&default_node)==B_OK) {
342 		roster->GetDormantNodeFor(default_node, &node_info);
343 		item = FindMediaListItem(&node_info);
344 		if (item)
345 			item->SetDefault(true, true);
346 		fAudioView->SetDefault(node_info, true);
347 	}
348 
349 	if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) {
350 		roster->GetDormantNodeFor(default_node, &node_info);
351 		item = FindMediaListItem(&node_info);
352 		if (item)
353 			item->SetDefault(true, false);
354 		fAudioView->SetDefault(node_info, false, outputID);
355 	}
356 
357 	if (roster->GetVideoInput(&default_node)==B_OK) {
358 		roster->GetDormantNodeFor(default_node, &node_info);
359 		item = FindMediaListItem(&node_info);
360 		if (item)
361 			item->SetDefault(true, true);
362 		fVideoView->SetDefault(node_info, true);
363 	}
364 
365 	if (roster->GetVideoOutput(&default_node)==B_OK) {
366 		roster->GetDormantNodeFor(default_node, &node_info);
367 		item = FindMediaListItem(&node_info);
368 		if (item)
369 			item->SetDefault(true, false);
370 		fVideoView->SetDefault(node_info, false);
371 	}
372 
373 	if (first) {
374 		fListView->Select(fListView->IndexOf(mixer));
375 	} else {
376 		if (!fAudioView->fRestartView->IsHidden())
377 			fAudioView->fRestartView->Hide();
378 		if (!fVideoView->fRestartView->IsHidden())
379 			fVideoView->fRestartView->Hide();
380 
381 		if (isVideoSelected)
382 			fListView->Select(fListView->IndexOf(video));
383 		else
384 			fListView->Select(fListView->IndexOf(audio));
385 	}
386 
387 	if (fAlert) {
388 		snooze(800000);
389 		fAlert->PostMessage(B_QUIT_REQUESTED);
390 	}
391 	fAlert = NULL;
392 
393 	Unlock();
394 
395 	return B_OK;
396 }
397 
398 
399 // MediaWindow::QuitRequested -- Post a message to the app to quit
400 bool
401 MediaWindow::QuitRequested()
402 {
403 	// stop watching the MediaRoster
404 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
405 	if (roster && fCurrentNode)	{
406 		roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
407 	}
408 	be_app->PostMessage(B_QUIT_REQUESTED);
409 	return true;
410 }
411 // ---------------------------------------------------------------------------------------------------------- //
412 
413 
414 // MediaWindow::FrameResized -- When the main frame is resized fix up the other views
415 void
416 MediaWindow::FrameResized (float width, float height)
417 {
418 	// This makes sure our SideBar colours down to the bottom when resized
419 	BRect r;
420 	r = Bounds();
421 }
422 // ---------------------------------------------------------------------------------------------------------- //
423 
424 // ErrorAlert -- Displays a BAlert Box with a Custom Error or Debug Message
425 void
426 ErrorAlert(char* errorMessage) {
427 	printf("%s\n", errorMessage);
428 	BAlert *alert = new BAlert("BAlert", errorMessage, B_TRANSLATE("OK"),
429 		NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
430 	alert->Go();
431 	exit(1);
432 }
433 // ---------------------------------------------------------------------------------------------------------- //
434 
435 
436 // MediaWindow::MessageReceived -- receives messages
437 void
438 MediaWindow::MessageReceived (BMessage *message)
439 {
440 	switch(message->what)
441 	{
442 		case ML_INIT_MEDIA:
443 			InitMedia(false);
444 			break;
445 		case ML_DEFAULTOUTPUT_CHANGE:
446 			{
447 				int32 index;
448 				if (message->FindInt32("index", &index)!=B_OK)
449 					break;
450 				Settings2Item *item = static_cast<Settings2Item *>(fAudioView->fMenu3->ItemAt(index));
451 
452 				if (item) {
453 					BMediaRoster *roster = BMediaRoster::Roster();
454 					roster->SetAudioOutput(*item->fInput);
455 
456 					if (fAudioView->fRestartView->IsHidden())
457 						fAudioView->fRestartView->Show();
458 				} else
459 					fprintf(stderr, "Settings2Item not found\n");
460 			}
461 			break;
462 		case ML_DEFAULT_CHANGE:
463 			{
464 				bool isVideo = true;
465 				bool isInput = true;
466 				if (message->FindBool("isVideo", &isVideo)!=B_OK)
467 					break;
468 				if (message->FindBool("isInput", &isInput)!=B_OK)
469 					break;
470 				int32 index;
471 				if (message->FindInt32("index", &index)!=B_OK)
472 					break;
473 				SettingsView *settingsView = isVideo ? fVideoView : fAudioView;
474 				BMenu *menu = isInput ? settingsView->fMenu1 : settingsView->fMenu2;
475 				SettingsItem *item = static_cast<SettingsItem *>(menu->ItemAt(index));
476 
477 				if (item) {
478 					PRINT(("isVideo %i isInput %i\n", isVideo, isInput));
479 					BMediaRoster *roster = BMediaRoster::Roster();
480 					if (isVideo) {
481 						if (isInput)
482 							roster->SetVideoInput(*item->fInfo);
483 						else
484 							roster->SetVideoOutput(*item->fInfo);
485 					} else {
486 						if (isInput)
487 							roster->SetAudioInput(*item->fInfo);
488 						else {
489 							roster->SetAudioOutput(*item->fInfo);
490 							fAudioView->SetDefault(*item->fInfo, false, 0);
491 						}
492 					}
493 
494 					MediaListItem *oldListItem = NULL;
495 					for (int32 j = 0; j<fListView->CountItems(); j++) {
496 						oldListItem = static_cast<MediaListItem *>(fListView->ItemAt(j));
497 						if (oldListItem->fInfo && oldListItem->IsVideo() == isVideo
498 							&& oldListItem->IsDefault(isInput))
499 							break;
500 					}
501 					if (oldListItem)
502 						oldListItem->SetDefault(false, isInput);
503 					else
504 						fprintf(stderr, "oldListItem not found\n");
505 
506 					MediaListItem *listItem = FindMediaListItem(item->fInfo);
507 					if (listItem) {
508 						listItem->SetDefault(true, isInput);
509 					} else
510 						fprintf(stderr, "MediaListItem not found\n");
511 					fListView->Invalidate();
512 
513 					if (settingsView->fRestartView->IsHidden())
514 						settingsView->fRestartView->Show();
515 				} else
516 					fprintf(stderr, "SettingsItem not found\n");
517 			}
518 			break;
519 		case ML_RESTART_MEDIA_SERVER:
520 		{
521 			thread_id thread = spawn_thread(&MediaWindow::RestartMediaServices,
522 				"restart_thread", B_NORMAL_PRIORITY, this);
523 			if (thread < B_OK)
524 				fprintf(stderr, "couldn't create restart thread\n");
525 			else
526 				resume_thread(thread);
527 			break;
528 		}
529 		case ML_SHOW_VOLUME_CONTROL:
530 		{
531 			BDeskbar deskbar;
532 			if (fAudioView->fVolumeCheckBox->Value() == B_CONTROL_ON) {
533 				BEntry entry("/bin/desklink", true);
534 				int32 id;
535 				entry_ref ref;
536 				status_t status = entry.GetRef(&ref);
537 				if (status == B_OK)
538 					status = deskbar.AddItem(&ref, &id);
539 
540 				if (status != B_OK) {
541 					fprintf(stderr, B_TRANSLATE(
542 						"Couldn't add volume control in Deskbar: %s\n"),
543 						strerror(status));
544 				}
545 			} else {
546 				status_t status = deskbar.RemoveItem("MediaReplicant");
547 				if (status != B_OK) {
548 					fprintf(stderr, B_TRANSLATE(
549 						"Couldn't remove volume control in Deskbar: %s\n"),
550 						strerror(status));
551 				}
552 			}
553 			break;
554 		}
555 		case ML_ENABLE_REAL_TIME:
556 			{
557 				bool isVideo = true;
558 				if (message->FindBool("isVideo", &isVideo)!=B_OK)
559 					break;
560 				SettingsView *settingsView = isVideo ? fVideoView : fAudioView;
561 				uint32 flags;
562 				uint32 realtimeFlag = isVideo ? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO;
563 				BMediaRoster *roster = BMediaRoster::Roster();
564 				roster->GetRealtimeFlags(&flags);
565 				if (settingsView->fRealtimeCheckBox->Value()==B_CONTROL_ON)
566 					flags |= realtimeFlag;
567 				else
568 					flags &= ~realtimeFlag;
569 				roster->SetRealtimeFlags(flags);
570 			}
571 			break;
572 		case B_MEDIA_WEB_CHANGED:
573 		case ML_SELECTED_NODE:
574 			{
575 				PRINT_OBJECT(*message);
576 
577 				MediaListItem *item = static_cast<MediaListItem *>(fListView->ItemAt(fListView->CurrentSelection()));
578 				if (!item)
579 					break;
580 				BMediaRoster* roster = BMediaRoster::Roster();
581 				if (fCurrentNode) {
582 					// stop watching the MediaRoster
583 					roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
584 					roster->ReleaseNode(*fCurrentNode);
585 				}
586 				fCurrentNode = NULL;
587 				BView *paramView = fContentView->ChildAt(0);
588 				if (paramView!=NULL) {
589 					fContentView->RemoveChild(paramView);
590 				}
591 				paramView = NULL;
592 				if (fParamWeb)
593 					delete fParamWeb;
594 				fParamWeb = NULL;
595 
596 				fTitleView->SetText(item->GetLabel());
597 
598 				if (item->OutlineLevel() == 0) {
599 					if (item->IsVideo())
600 						fContentView->AddChild(fVideoView);
601 					else
602 						fContentView->AddChild(fAudioView);
603 				} else {
604 
605 					if (!fCurrentNode)
606 						fCurrentNode = new media_node();
607 					media_node_id node_id;
608 					if (item->IsAudioMixer())
609 						roster->GetAudioMixer(fCurrentNode);
610 					else if (roster->GetInstancesFor(item->fInfo->addon, item->fInfo->flavor_id, &node_id)!=B_OK)
611 						roster->InstantiateDormantNode(*(item->fInfo), fCurrentNode, B_FLAVOR_IS_GLOBAL);
612 					else
613 						roster->GetNodeFor(node_id, fCurrentNode);
614 
615 					if (roster->GetParameterWebFor(*fCurrentNode, &fParamWeb)==B_OK
616 						&& (paramView = BMediaTheme::PreferredTheme()->ViewFor(fParamWeb)) != NULL) {
617 						fContentView->AddChild(paramView);
618 						paramView->ResizeTo(fContentView->Bounds().Width(), fContentView->Bounds().Height() - 10);
619 
620 						roster->StartWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
621 					} else {
622 						if (fParamWeb)
623 							delete fParamWeb;
624 						fParamWeb = NULL;
625 						BRect bounds = fContentView->Bounds();
626 						BStringView* stringView = new BStringView(bounds,
627 							"noControls", B_TRANSLATE("This hardware has no controls."),
628 							B_FOLLOW_V_CENTER | B_FOLLOW_H_CENTER);
629 						stringView->ResizeToPreferred();
630 						fContentView->AddChild(stringView);
631 						stringView->MoveBy((bounds.Width()-stringView->Bounds().Width())/2,
632 							(bounds.Height()-stringView->Bounds().Height())/2);
633 					}
634 				}
635 
636 				bool barChanged = (item->OutlineLevel() == 0 || fParamWeb == NULL || fParamWeb->CountGroups()<2);
637 				if (barChanged != fBar->fDisplay) {
638 					fBar->fDisplay = barChanged;
639 					fBar->Invalidate();
640 				}
641 			}
642 			break;
643 		case B_SOME_APP_LAUNCHED:
644 			{
645 				PRINT_OBJECT(*message);
646 				const char *mimeSig;
647 				if (fAlert && message->FindString("be:signature", &mimeSig)==B_OK
648 					&& (strcmp(mimeSig, "application/x-vnd.Be.addon-host")==0
649 						|| strcmp(mimeSig, "application/x-vnd.Be.media-server")==0)) {
650 					fAlert->Lock();
651 					fAlert->TextView()->SetText(
652 						B_TRANSLATE("Starting media server" B_UTF8_ELLIPSIS));
653 					fAlert->Unlock();
654 				}
655 			}
656 			break;
657 		case B_SOME_APP_QUIT:
658 			{
659 				PRINT_OBJECT(*message);
660 				const char *mimeSig;
661 				if (message->FindString("be:signature", &mimeSig)==B_OK) {
662 					if (strcmp(mimeSig, "application/x-vnd.Be.addon-host")==0
663 						|| strcmp(mimeSig, "application/x-vnd.Be.media-server")==0) {
664 						BMediaRoster* roster = BMediaRoster::CurrentRoster();
665 						if (roster&&roster->Lock())
666 							roster->Quit();
667 					}
668 				}
669 
670 			}
671 			break;
672 		default:
673 			BWindow::MessageReceived(message);
674 			break;
675 	}
676 }
677 
678 status_t
679 MediaWindow::RestartMediaServices(void *data)
680 {
681 	MediaWindow *window = (MediaWindow *)data;
682 	window->fAlert = new MediaAlert(BRect(0, 0, 300, 60),
683 		"restart_alert", B_TRANSLATE(
684 		"Restarting media services\nShutting down media server\n"));
685 
686 	window->fAlert->Show();
687 
688 	shutdown_media_server(B_INFINITE_TIMEOUT, MediaWindow::UpdateProgress, window->fAlert);
689 
690 	{
691 		BAutolock locker(window->fAlert);
692 		if (locker.IsLocked())
693 			window->fAlert->TextView()->SetText(
694 				B_TRANSLATE("Starting media server" B_UTF8_ELLIPSIS));
695 	}
696 	launch_media_server();
697 
698 	return window->PostMessage(ML_INIT_MEDIA);
699 }
700 
701 bool
702 MediaWindow::UpdateProgress(int stage, const char * message, void * cookie)
703 {
704 	MediaAlert *alert = static_cast<MediaAlert*>(cookie);
705 	PRINT(("stage : %i\n", stage));
706 	const char *string = "Unknown stage";
707 	switch (stage) {
708 		case 10:
709 			string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
710 			break;
711 		case 20:
712 			string = B_TRANSLATE("Telling media_addon_server to quit.");
713 			break;
714 		case 40:
715 			string = B_TRANSLATE("Waiting for media_server to quit.");
716 			break;
717 		case 70:
718 			string = B_TRANSLATE("Cleaning up.");
719 			break;
720 		case 100:
721 			string = B_TRANSLATE("Done shutting down.");
722 			break;
723 	}
724 
725 	BAutolock locker(alert);
726 	if (locker.IsLocked())
727 		alert->TextView()->SetText(string);
728 	return true;
729 }
730 
731