xref: /haiku/src/preferences/media/MediaWindow.cpp (revision 37344020ef592f58c61b7de8cd2c83dd31203aca)
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 "MediaWindow.h"
11 
12 #include <stdio.h>
13 
14 #include <Alert.h>
15 #include <Application.h>
16 #include <Autolock.h>
17 #include <Bitmap.h>
18 #include <Button.h>
19 #include <Catalog.h>
20 #include <Debug.h>
21 #include <Deskbar.h>
22 #include <GroupView.h>
23 #include <Locale.h>
24 #include <MediaRoster.h>
25 #include <MediaTheme.h>
26 #include <Roster.h>
27 #include <Screen.h>
28 #include <ScrollView.h>
29 #include <SpaceLayoutItem.h>
30 #include <StorageKit.h>
31 #include <String.h>
32 #include <TextView.h>
33 
34 // Images
35 #include "iconfile.h"
36 
37 
38 #undef B_TRANSLATE_CONTEXT
39 #define B_TRANSLATE_CONTEXT "Media Window"
40 
41 
42 const uint32 ML_SELECTED_NODE = 'MlSN';
43 const uint32 ML_INIT_MEDIA = 'MlIM';
44 
45 // MediaWindow - Constructor
46 MediaWindow::MediaWindow(BRect frame)
47 	:
48 	BWindow (frame, B_TRANSLATE("Media"), B_TITLED_WINDOW,
49 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
50 	fCurrentNode(NULL),
51 	fParamWeb(NULL),
52 	fAlert(NULL),
53 	fInitCheck(B_OK)
54 {
55 	InitWindow();
56 }
57 
58 
59 status_t
60 MediaWindow::InitCheck()
61 {
62 	return fInitCheck;
63 }
64 
65 
66 MediaWindow::~MediaWindow()
67 {
68 	for (int i = 0; i < fAudioOutputs.CountItems(); i++)
69 		delete static_cast<dormant_node_info*>(fAudioOutputs.ItemAt(i));
70 	for (int i = 0; i < fAudioInputs.CountItems(); i++)
71 		delete static_cast<dormant_node_info*>(fAudioInputs.ItemAt(i));
72 	for (int i = 0; i < fVideoOutputs.CountItems(); i++)
73 		delete static_cast<dormant_node_info*>(fVideoOutputs.ItemAt(i));
74 	for (int i = 0; i < fVideoInputs.CountItems(); i++)
75 		delete static_cast<dormant_node_info*>(fVideoInputs.ItemAt(i));
76 
77 	BMediaRoster* roster = BMediaRoster::Roster();
78 	if (roster && fCurrentNode)
79 		roster->ReleaseNode(*fCurrentNode);
80 
81 	char buffer[512];
82 	BRect rect = Frame();
83 	PRINT_OBJECT(rect);
84 	sprintf(buffer, "# MediaPrefs Settings\n rect = %i,%i,%i,%i\n",
85 		int(rect.left), int(rect.top), int(rect.right), int(rect.bottom));
86 
87 	BPath path;
88 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
89 		path.Append(SETTINGS_FILE);
90 		BFile file(path.Path(), B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE);
91 		if (file.InitCheck()==B_OK) {
92 			file.Write(buffer, strlen(buffer));
93 		}
94 	}
95 }
96 
97 
98 void
99 MediaWindow::FindNodes(media_type type, uint64 kind, BList &list)
100 {
101 	dormant_node_info node_info[64];
102 	int32 node_info_count = 64;
103 	media_format format;
104 	media_format* format1 = NULL, *format2 = NULL;
105 	BMediaRoster* roster = BMediaRoster::Roster();
106 	format.type = type;
107 
108 	if (kind & B_PHYSICAL_OUTPUT)
109 		format1 = &format;
110 	else if (kind & B_PHYSICAL_INPUT)
111 		format2 = &format;
112 	else
113 		return;
114 
115 	if (roster->GetDormantNodes(node_info, &node_info_count, format1, format2,
116 			NULL, kind)!=B_OK) {
117 		fprintf(stderr, "error\n");
118 		return;
119 	}
120 
121 	for (int32 i = 0; i<node_info_count; i++) {
122 		PRINT(("node : %s, media_addon %i, flavor_id %i\n",
123 			node_info[i].name, node_info[i].addon, node_info[i].flavor_id));
124 		dormant_node_info* info = new dormant_node_info();
125 		strcpy(info->name, node_info[i].name);
126 		info->flavor_id = node_info[i].flavor_id;
127 		info->addon = node_info[i].addon;
128 		list.AddItem(info);
129 	}
130 }
131 
132 
133 MediaListItem *
134 MediaWindow::FindMediaListItem(dormant_node_info* info)
135 {
136 	for (int32 j = 0; j<fListView->CountItems(); j++) {
137 		MediaListItem* item
138 			= static_cast<MediaListItem *>(fListView->ItemAt(j));
139 		if (item->fInfo && item->fInfo->addon == info->addon
140 				&& item->fInfo->flavor_id == info->flavor_id) {
141 			return item;
142 			break;
143 		}
144 	}
145 	return NULL;
146 }
147 
148 
149 void
150 MediaWindow::AddNodes(BList &list, bool isVideo)
151 {
152 	for (int32 i = 0; i<list.CountItems(); i++) {
153 		dormant_node_info* info
154 			= static_cast<dormant_node_info*>(list.ItemAt(i));
155 		if (!FindMediaListItem(info))
156 			fListView->AddItem(new MediaListItem(info, 1, isVideo, &fIcons));
157 	}
158 }
159 
160 
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 	// Grab Media Info
305 	FindNodes(B_MEDIA_RAW_AUDIO, B_PHYSICAL_OUTPUT, fAudioOutputs);
306 	FindNodes(B_MEDIA_RAW_AUDIO, B_PHYSICAL_INPUT, fAudioInputs);
307 	FindNodes(B_MEDIA_ENCODED_AUDIO, B_PHYSICAL_OUTPUT, fAudioOutputs);
308 	FindNodes(B_MEDIA_ENCODED_AUDIO, B_PHYSICAL_INPUT, fAudioInputs);
309 	FindNodes(B_MEDIA_RAW_VIDEO, B_PHYSICAL_OUTPUT, fVideoOutputs);
310 	FindNodes(B_MEDIA_RAW_VIDEO, B_PHYSICAL_INPUT, fVideoInputs);
311 	FindNodes(B_MEDIA_ENCODED_VIDEO, B_PHYSICAL_OUTPUT, fVideoOutputs);
312 	FindNodes(B_MEDIA_ENCODED_VIDEO, B_PHYSICAL_INPUT, fVideoInputs);
313 
314 	// Add video nodes first. They might have an additional audio
315 	// output or input, but still should be listed as video node.
316 	AddNodes(fVideoOutputs, true);
317 	AddNodes(fVideoInputs, true);
318 	AddNodes(fAudioOutputs, false);
319 	AddNodes(fAudioInputs, false);
320 
321 	fAudioView->AddNodes(fAudioOutputs, false);
322 	fAudioView->AddNodes(fAudioInputs, true);
323 	fVideoView->AddNodes(fVideoOutputs, false);
324 	fVideoView->AddNodes(fVideoInputs, true);
325 
326 	// build our list view
327 	MediaListItem* audio = new MediaListItem(B_TRANSLATE("Audio settings"), 0,
328 		false, &fIcons);
329 	fListView->AddItem(audio);
330 
331 	MediaListItem* video = new MediaListItem(B_TRANSLATE("Video settings"), 0,
332 		true, &fIcons);
333 	fListView->AddItem(video);
334 
335 	MediaListItem* mixer = new MediaListItem(B_TRANSLATE("Audio mixer"),
336 		1, false, &fIcons);
337 	fListView->AddItem(mixer);
338 	mixer->SetAudioMixer(true);
339 
340 	fListView->SortItems(&MediaListItem::Compare);
341 
342 	// Set default nodes for our setting views
343 	media_node default_node;
344 	dormant_node_info node_info;
345 	int32 outputID;
346 	BString outputName;
347 
348 	if (roster->GetAudioInput(&default_node) == B_OK) {
349 		roster->GetDormantNodeFor(default_node, &node_info);
350 		MediaListItem* item = FindMediaListItem(&node_info);
351 		if (item)
352 			item->SetDefault(true, true);
353 		fAudioView->SetDefault(node_info, true);
354 	}
355 
356 	if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) {
357 		roster->GetDormantNodeFor(default_node, &node_info);
358 		MediaListItem* item = FindMediaListItem(&node_info);
359 		if (item)
360 			item->SetDefault(true, false);
361 		fAudioView->SetDefault(node_info, false, outputID);
362 	}
363 
364 	if (roster->GetVideoInput(&default_node)==B_OK) {
365 		roster->GetDormantNodeFor(default_node, &node_info);
366 		MediaListItem* item = FindMediaListItem(&node_info);
367 		if (item)
368 			item->SetDefault(true, true);
369 		fVideoView->SetDefault(node_info, true);
370 	}
371 
372 	if (roster->GetVideoOutput(&default_node)==B_OK) {
373 		roster->GetDormantNodeFor(default_node, &node_info);
374 		MediaListItem* item = FindMediaListItem(&node_info);
375 		if (item)
376 			item->SetDefault(true, false);
377 		fVideoView->SetDefault(node_info, false);
378 	}
379 
380 	if (first) {
381 		fListView->Select(fListView->IndexOf(mixer));
382 	} else {
383 		if (!fAudioView->fRestartView->IsHidden())
384 			fAudioView->fRestartView->Hide();
385 		if (!fVideoView->fRestartView->IsHidden())
386 			fVideoView->fRestartView->Hide();
387 
388 		if (isVideoSelected)
389 			fListView->Select(fListView->IndexOf(video));
390 		else
391 			fListView->Select(fListView->IndexOf(audio));
392 	}
393 
394 	if (fAlert) {
395 		snooze(800000);
396 		fAlert->PostMessage(B_QUIT_REQUESTED);
397 	}
398 	fAlert = NULL;
399 
400 	Unlock();
401 
402 	return B_OK;
403 }
404 
405 
406 bool
407 MediaWindow::QuitRequested()
408 {
409 	// stop watching the MediaRoster
410 	BMediaRoster* roster = BMediaRoster::CurrentRoster();
411 	if (roster && fCurrentNode)	{
412 		roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
413 	}
414 	be_app->PostMessage(B_QUIT_REQUESTED);
415 	return true;
416 }
417 
418 
419 void
420 MediaWindow::FrameResized (float width, float height)
421 {
422 	// This makes sure our SideBar colours down to the bottom when resized
423 	BRect r;
424 	r = Bounds();
425 }
426 
427 
428 // ErrorAlert -- Displays a BAlert Box with a Custom Error or Debug Message
429 void
430 ErrorAlert(char* errorMessage) {
431 	printf("%s\n", errorMessage);
432 	BAlert* alert = new BAlert("BAlert", errorMessage, B_TRANSLATE("OK"),
433 		NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
434 	alert->Go();
435 	exit(1);
436 }
437 
438 
439 void
440 MediaWindow::MessageReceived(BMessage* message)
441 {
442 	switch(message->what)
443 	{
444 		case ML_INIT_MEDIA:
445 			InitMedia(false);
446 			break;
447 		case ML_DEFAULTOUTPUT_CHANGE:
448 			{
449 				int32 index;
450 				if (message->FindInt32("index", &index)!=B_OK)
451 					break;
452 				Settings2Item* item = static_cast<Settings2Item*>(
453 					fAudioView->fMenu3->ItemAt(index));
454 
455 				if (item) {
456 					BMediaRoster* roster = BMediaRoster::Roster();
457 					roster->SetAudioOutput(*item->fInput);
458 
459 					if (fAudioView->fRestartView->IsHidden())
460 						fAudioView->fRestartView->Show();
461 				} else
462 					fprintf(stderr, "Settings2Item not found\n");
463 			}
464 			break;
465 		case ML_DEFAULT_CHANGE:
466 			{
467 				bool isVideo = true;
468 				bool isInput = true;
469 				if (message->FindBool("isVideo", &isVideo)!=B_OK)
470 					break;
471 				if (message->FindBool("isInput", &isInput)!=B_OK)
472 					break;
473 				int32 index;
474 				if (message->FindInt32("index", &index)!=B_OK)
475 					break;
476 				SettingsView* settingsView = isVideo ? fVideoView : fAudioView;
477 				BMenu* menu = isInput ? settingsView->fMenu1
478 					: settingsView->fMenu2;
479 				SettingsItem* item = static_cast<SettingsItem*>(
480 					menu->ItemAt(index));
481 
482 				if (item) {
483 					PRINT(("isVideo %i isInput %i\n", isVideo, isInput));
484 					BMediaRoster* roster = BMediaRoster::Roster();
485 					if (isVideo) {
486 						if (isInput)
487 							roster->SetVideoInput(*item->fInfo);
488 						else
489 							roster->SetVideoOutput(*item->fInfo);
490 					} else {
491 						if (isInput)
492 							roster->SetAudioInput(*item->fInfo);
493 						else {
494 							roster->SetAudioOutput(*item->fInfo);
495 							fAudioView->SetDefault(*item->fInfo, false, 0);
496 						}
497 					}
498 
499 					MediaListItem* oldListItem = NULL;
500 					for (int32 j = 0; j < fListView->CountItems(); j++) {
501 						oldListItem = static_cast<MediaListItem*>(
502 							fListView->ItemAt(j));
503 						if (oldListItem->fInfo
504 							&& oldListItem->IsVideo() == isVideo
505 							&& oldListItem->IsDefault(isInput))
506 							break;
507 					}
508 					if (oldListItem)
509 						oldListItem->SetDefault(false, isInput);
510 					else
511 						fprintf(stderr, "oldListItem not found\n");
512 
513 					MediaListItem* listItem = FindMediaListItem(item->fInfo);
514 					if (listItem) {
515 						listItem->SetDefault(true, isInput);
516 					} else
517 						fprintf(stderr, "MediaListItem not found\n");
518 					fListView->Invalidate();
519 
520 					if (settingsView->fRestartView->IsHidden())
521 						settingsView->fRestartView->Show();
522 				} else
523 					fprintf(stderr, "SettingsItem not found\n");
524 			}
525 			break;
526 		case ML_RESTART_MEDIA_SERVER:
527 		{
528 			thread_id thread = spawn_thread(&MediaWindow::RestartMediaServices,
529 				"restart_thread", B_NORMAL_PRIORITY, this);
530 			if (thread < B_OK)
531 				fprintf(stderr, "couldn't create restart thread\n");
532 			else
533 				resume_thread(thread);
534 			break;
535 		}
536 		case ML_SHOW_VOLUME_CONTROL:
537 		{
538 			BDeskbar deskbar;
539 			if (fAudioView->fVolumeCheckBox->Value() == B_CONTROL_ON) {
540 				BEntry entry("/bin/desklink", true);
541 				int32 id;
542 				entry_ref ref;
543 				status_t status = entry.GetRef(&ref);
544 				if (status == B_OK)
545 					status = deskbar.AddItem(&ref, &id);
546 
547 				if (status != B_OK) {
548 					fprintf(stderr, B_TRANSLATE(
549 						"Couldn't add volume control in Deskbar: %s\n"),
550 						strerror(status));
551 				}
552 			} else {
553 				status_t status = deskbar.RemoveItem("MediaReplicant");
554 				if (status != B_OK) {
555 					fprintf(stderr, B_TRANSLATE(
556 						"Couldn't remove volume control in Deskbar: %s\n"),
557 						strerror(status));
558 				}
559 			}
560 			break;
561 		}
562 		case ML_ENABLE_REAL_TIME:
563 			{
564 				bool isVideo = true;
565 				if (message->FindBool("isVideo", &isVideo)!=B_OK)
566 					break;
567 				SettingsView* settingsView = isVideo ? fVideoView : fAudioView;
568 				uint32 flags;
569 				uint32 realtimeFlag = isVideo
570 					? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO;
571 				BMediaRoster* roster = BMediaRoster::Roster();
572 				roster->GetRealtimeFlags(&flags);
573 				if (settingsView->fRealtimeCheckBox->Value() == B_CONTROL_ON)
574 					flags |= realtimeFlag;
575 				else
576 					flags &= ~realtimeFlag;
577 				roster->SetRealtimeFlags(flags);
578 			}
579 			break;
580 		case B_MEDIA_WEB_CHANGED:
581 		case ML_SELECTED_NODE:
582 			{
583 				PRINT_OBJECT(*message);
584 
585 				MediaListItem* item = static_cast<MediaListItem*>(
586 						fListView->ItemAt(fListView->CurrentSelection()));
587 				if (!item)
588 					break;
589 				BMediaRoster* roster = BMediaRoster::Roster();
590 				if (fCurrentNode) {
591 					// stop watching the MediaRoster
592 					roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
593 					roster->ReleaseNode(*fCurrentNode);
594 				}
595 				fCurrentNode = NULL;
596 				BView* paramView = fContentView->ChildAt(0);
597 				if (paramView!=NULL) {
598 					fContentView->RemoveChild(paramView);
599 				}
600 				paramView = NULL;
601 				if (fParamWeb)
602 					delete fParamWeb;
603 				fParamWeb = NULL;
604 
605 				fTitleView->SetText(item->GetLabel());
606 
607 				if (item->OutlineLevel() == 0) {
608 					if (item->IsVideo())
609 						fContentView->AddChild(fVideoView);
610 					else
611 						fContentView->AddChild(fAudioView);
612 				} else {
613 
614 					if (!fCurrentNode)
615 						fCurrentNode = new media_node();
616 					media_node_id node_id;
617 					if (item->IsAudioMixer())
618 						roster->GetAudioMixer(fCurrentNode);
619 					else if (roster->GetInstancesFor(item->fInfo->addon, item->fInfo->flavor_id, &node_id)!=B_OK)
620 						roster->InstantiateDormantNode(*(item->fInfo), fCurrentNode, B_FLAVOR_IS_GLOBAL);
621 					else
622 						roster->GetNodeFor(node_id, fCurrentNode);
623 
624 					if (roster->GetParameterWebFor(*fCurrentNode, &fParamWeb)==B_OK
625 						&& (paramView = BMediaTheme::PreferredTheme()->ViewFor(fParamWeb)) != NULL) {
626 						fContentView->AddChild(paramView);
627 						paramView->ResizeTo(fContentView->Bounds().Width(), fContentView->Bounds().Height() - 10);
628 
629 						roster->StartWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
630 					} else {
631 						delete fParamWeb;
632 						fParamWeb = NULL;
633 
634 						BRect bounds = fContentView->Bounds();
635 						BStringView* stringView = new BStringView(bounds,
636 							"noControls", B_TRANSLATE("This hardware has no controls."),
637 							B_FOLLOW_V_CENTER | B_FOLLOW_H_CENTER);
638 						stringView->ResizeToPreferred();
639 						fContentView->AddChild(stringView);
640 						stringView->MoveBy((bounds.Width()-stringView->Bounds().Width())/2,
641 							(bounds.Height()-stringView->Bounds().Height())/2);
642 					}
643 				}
644 
645 				bool barChanged = (item->OutlineLevel() == 0
646 					|| fParamWeb == NULL || fParamWeb->CountGroups()<2);
647 				if (barChanged != fBar->fDisplay) {
648 					fBar->fDisplay = barChanged;
649 					fBar->Invalidate();
650 				}
651 			}
652 			break;
653 		case B_SOME_APP_LAUNCHED:
654 			{
655 				PRINT_OBJECT(*message);
656 				if (!fAlert)
657 					break;
658 
659 				BString mimeSig;
660 				if (message->FindString("be:signature", &mimeSig) == B_OK
661 					&& (mimeSig == "application/x-vnd.Be.addon-host"
662 						|| mimeSig == "application/x-vnd.Be.media-server")) {
663 					fAlert->Lock();
664 					fAlert->TextView()->SetText(
665 						B_TRANSLATE("Starting media server" B_UTF8_ELLIPSIS));
666 					fAlert->Unlock();
667 				}
668 			}
669 			break;
670 		case B_SOME_APP_QUIT:
671 			{
672 				PRINT_OBJECT(*message);
673 				BString mimeSig;
674 				if (message->FindString("be:signature", &mimeSig) == B_OK) {
675 					if (mimeSig == "application/x-vnd.Be.addon-host"
676 						|| mimeSig == "application/x-vnd.Be.media-server") {
677 						BMediaRoster* roster = BMediaRoster::CurrentRoster();
678 						if (roster && roster->Lock())
679 							roster->Quit();
680 					}
681 				}
682 
683 			}
684 			break;
685 		default:
686 			BWindow::MessageReceived(message);
687 			break;
688 	}
689 }
690 
691 status_t
692 MediaWindow::RestartMediaServices(void* data)
693 {
694 	MediaWindow* window = (MediaWindow*)data;
695 	window->fAlert = new MediaAlert(BRect(0, 0, 300, 60),
696 		"restart_alert", B_TRANSLATE(
697 		"Restarting media services\nShutting down media server\n"));
698 
699 	window->fAlert->Show();
700 
701 	shutdown_media_server(B_INFINITE_TIMEOUT, MediaWindow::UpdateProgress,
702 		window->fAlert);
703 
704 	{
705 		BAutolock locker(window->fAlert);
706 		if (locker.IsLocked())
707 			window->fAlert->TextView()->SetText(
708 				B_TRANSLATE("Starting media server" B_UTF8_ELLIPSIS));
709 	}
710 	launch_media_server();
711 
712 	return window->PostMessage(ML_INIT_MEDIA);
713 }
714 
715 
716 bool
717 MediaWindow::UpdateProgress(int stage, const char * message, void * cookie)
718 {
719 	MediaAlert* alert = static_cast<MediaAlert*>(cookie);
720 	PRINT(("stage : %i\n", stage));
721 	const char* string = "Unknown stage";
722 	switch (stage) {
723 		case 10:
724 			string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
725 			break;
726 		case 20:
727 			string = B_TRANSLATE("Telling media_addon_server to quit.");
728 			break;
729 		case 40:
730 			string = B_TRANSLATE("Waiting for media_server to quit.");
731 			break;
732 		case 70:
733 			string = B_TRANSLATE("Cleaning up.");
734 			break;
735 		case 100:
736 			string = B_TRANSLATE("Done shutting down.");
737 			break;
738 	}
739 
740 	BAutolock locker(alert);
741 	if (locker.IsLocked())
742 		alert->TextView()->SetText(string);
743 	return true;
744 }
745 
746