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