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