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