xref: /haiku/src/preferences/media/MediaViews.cpp (revision 7afc7756306b3fd9667d03fba787e3aa8b60cab5)
1a10cf76eSAxel Dörfler // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
2a10cf76eSAxel Dörfler //
3a10cf76eSAxel Dörfler //	Copyright (c) 2003, OpenBeOS
4a10cf76eSAxel Dörfler //
5a10cf76eSAxel Dörfler //  This software is part of the OpenBeOS distribution and is covered
6a10cf76eSAxel Dörfler //  by the OpenBeOS license.
7a10cf76eSAxel Dörfler //
8a10cf76eSAxel Dörfler //
9a10cf76eSAxel Dörfler //  File:        MediaViews.cpp
10a10cf76eSAxel Dörfler //  Author:      Sikosis, Jérôme Duval
11a10cf76eSAxel Dörfler //  Description: Media Preferences
12a10cf76eSAxel Dörfler //  Created :    June 25, 2003
13a10cf76eSAxel Dörfler //
14a10cf76eSAxel Dörfler // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
15a633251fSAlex Wilson #include "MediaViews.h"
16f8a1135cSAdrien Destugues 
17*7afc7756SAlex Wilson #include <AutoDeleter.h>
18a10cf76eSAxel Dörfler #include <Box.h>
19a10cf76eSAxel Dörfler #include <Button.h>
20f8a1135cSAdrien Destugues #include <Catalog.h>
21*7afc7756SAlex Wilson #include <CheckBox.h>
22a10cf76eSAxel Dörfler #include <Deskbar.h>
23a10cf76eSAxel Dörfler #include <Entry.h>
24*7afc7756SAlex Wilson #include <LayoutBuilder.h>
25f8a1135cSAdrien Destugues #include <Locale.h>
26a10cf76eSAxel Dörfler #include <MediaAddOn.h>
27f8a1135cSAdrien Destugues #include <MediaRoster.h>
28f8a1135cSAdrien Destugues #include <MenuField.h>
29f8a1135cSAdrien Destugues #include <PopUpMenu.h>
30a10cf76eSAxel Dörfler #include <String.h>
31*7afc7756SAlex Wilson #include <StringView.h>
32b4a12470SJérôme Duval #include <TextView.h>
332af5f895SStephan Aßmus 
34*7afc7756SAlex Wilson #include <assert.h>
35a633251fSAlex Wilson #include <stdio.h>
36a10cf76eSAxel Dörfler 
37*7afc7756SAlex Wilson #include "MediaWindow.h"
38*7afc7756SAlex Wilson 
399cedafe6SWim van der Meer 
409cedafe6SWim van der Meer #undef B_TRANSLATE_CONTEXT
414eb0cbb0SMatt Madia #define B_TRANSLATE_CONTEXT "Media views"
42f8a1135cSAdrien Destugues 
43*7afc7756SAlex Wilson #define MEDIA_DEFAULT_INPUT_CHANGE 'dich'
44*7afc7756SAlex Wilson #define MEDIA_DEFAULT_OUTPUT_CHANGE 'doch'
45*7afc7756SAlex Wilson #define MEDIA_SHOW_HIDE_VOLUME_CONTROL 'shvc'
469cedafe6SWim van der Meer 
47*7afc7756SAlex Wilson 
48*7afc7756SAlex Wilson SettingsView::SettingsView()
49a633251fSAlex Wilson 	:
50*7afc7756SAlex Wilson 	BGridView(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING),
51*7afc7756SAlex Wilson 	fRealtimeCheckBox(NULL),
52*7afc7756SAlex Wilson 	fInputMenu(NULL),
53*7afc7756SAlex Wilson 	fOutputMenu(NULL),
54*7afc7756SAlex Wilson 	fRestartView(NULL)
55a10cf76eSAxel Dörfler {
566e62e744SAlex Wilson 	// input menu
576e62e744SAlex Wilson 	fInputMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
586e62e744SAlex Wilson 	fInputMenu->SetLabelFromMarked(true);
596e62e744SAlex Wilson 
60*7afc7756SAlex Wilson 	// input menu
616e62e744SAlex Wilson 	fOutputMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
626e62e744SAlex Wilson 	fOutputMenu->SetLabelFromMarked(true);
636e62e744SAlex Wilson }
646e62e744SAlex Wilson 
652af5f895SStephan Aßmus 
66*7afc7756SAlex Wilson BBox*
67*7afc7756SAlex Wilson SettingsView::MakeRealtimeBox(const char* info, uint32 realtimeMask,
68*7afc7756SAlex Wilson 	const char* checkBoxLabel)
69*7afc7756SAlex Wilson {
702af5f895SStephan Aßmus 	// create the realtime box
71c8602bcdSRene Gollent 	BBox* realtimeBox = new BBox("realtime");
72176fb40fSMatt Madia 	realtimeBox->SetLabel(B_TRANSLATE("Real-time"));
73a10cf76eSAxel Dörfler 
74*7afc7756SAlex Wilson 	BMessage* checkBoxMessage = new BMessage(ML_ENABLE_REAL_TIME);
75*7afc7756SAlex Wilson 	checkBoxMessage->AddUInt32("flags", realtimeMask);
76*7afc7756SAlex Wilson 	fRealtimeCheckBox = new BCheckBox("realtimeCheckBox", checkBoxLabel,
77*7afc7756SAlex Wilson 		checkBoxMessage);
78a10cf76eSAxel Dörfler 
79*7afc7756SAlex Wilson 	uint32 flags = 0;
80a10cf76eSAxel Dörfler 	BMediaRoster::Roster()->GetRealtimeFlags(&flags);
81*7afc7756SAlex Wilson 	if (flags & realtimeMask)
82b4a12470SJérôme Duval 		fRealtimeCheckBox->SetValue(B_CONTROL_ON);
83a10cf76eSAxel Dörfler 
84c8602bcdSRene Gollent 	BTextView* textView = new BTextView("stringView");
85*7afc7756SAlex Wilson 	textView->Insert(info);
86b4a12470SJérôme Duval 	textView->MakeEditable(false);
87b4a12470SJérôme Duval 	textView->MakeSelectable(false);
88a10cf76eSAxel Dörfler 	textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
89a10cf76eSAxel Dörfler 
90*7afc7756SAlex Wilson 	BGroupView* realtimeGroup = new BGroupView(B_VERTICAL);
91*7afc7756SAlex Wilson 	BLayoutBuilder::Group<>(realtimeGroup)
92*7afc7756SAlex Wilson 		.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
93*7afc7756SAlex Wilson 			B_USE_DEFAULT_SPACING)
94*7afc7756SAlex Wilson 		.Add(fRealtimeCheckBox)
95*7afc7756SAlex Wilson 		.Add(textView);
962af5f895SStephan Aßmus 
97*7afc7756SAlex Wilson 	realtimeBox->AddChild(realtimeGroup);
98*7afc7756SAlex Wilson 	return realtimeBox;
99*7afc7756SAlex Wilson }
1002af5f895SStephan Aßmus 
101*7afc7756SAlex Wilson 
102*7afc7756SAlex Wilson BStringView*
103*7afc7756SAlex Wilson SettingsView::MakeRestartMessageView()
104*7afc7756SAlex Wilson {
105*7afc7756SAlex Wilson 	// note: this ought to display at the bottom of the default box...
106*7afc7756SAlex Wilson 	fRestartView = new BStringView("restartStringView",
107*7afc7756SAlex Wilson 		B_TRANSLATE("Restart the media server to apply changes."));
108*7afc7756SAlex Wilson 	fRestartView->SetHighColor(ui_color(B_FAILURE_COLOR));
109*7afc7756SAlex Wilson 		// not exactly failure, but sort of.
110*7afc7756SAlex Wilson 	fRestartView->Hide();
111*7afc7756SAlex Wilson 	fRestartView->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER,
112*7afc7756SAlex Wilson 		B_ALIGN_VERTICAL_CENTER));
113*7afc7756SAlex Wilson 	fRestartView->SetAlignment(B_ALIGN_HORIZONTAL_CENTER);
114*7afc7756SAlex Wilson 	fRestartView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
115*7afc7756SAlex Wilson 	return fRestartView;
116*7afc7756SAlex Wilson }
117*7afc7756SAlex Wilson 
118*7afc7756SAlex Wilson 
119*7afc7756SAlex Wilson BButton*
120*7afc7756SAlex Wilson SettingsView::MakeRestartButton()
121*7afc7756SAlex Wilson {
122*7afc7756SAlex Wilson 	return new BButton("restartButton",
123176fb40fSMatt Madia 		B_TRANSLATE("Restart media services"),
124176fb40fSMatt Madia 		new BMessage(ML_RESTART_MEDIA_SERVER));
125a10cf76eSAxel Dörfler }
1262af5f895SStephan Aßmus 
1272af5f895SStephan Aßmus 
128*7afc7756SAlex Wilson 
129*7afc7756SAlex Wilson void
130*7afc7756SAlex Wilson SettingsView::AddInputNodes(NodeList& list)
131*7afc7756SAlex Wilson {
132*7afc7756SAlex Wilson 	_EmptyMenu(fInputMenu);
133*7afc7756SAlex Wilson 
134*7afc7756SAlex Wilson 	BMessage message(MEDIA_DEFAULT_INPUT_CHANGE);
135*7afc7756SAlex Wilson 	_PopulateMenu(fInputMenu, list, message);
136a10cf76eSAxel Dörfler }
137a10cf76eSAxel Dörfler 
138a633251fSAlex Wilson 
139a10cf76eSAxel Dörfler void
140*7afc7756SAlex Wilson SettingsView::AddOutputNodes(NodeList& list)
141a10cf76eSAxel Dörfler {
142*7afc7756SAlex Wilson 	_EmptyMenu(fOutputMenu);
1436e62e744SAlex Wilson 
144*7afc7756SAlex Wilson 	BMessage message(MEDIA_DEFAULT_OUTPUT_CHANGE);
145*7afc7756SAlex Wilson 	_PopulateMenu(fOutputMenu, list, message);
146a10cf76eSAxel Dörfler }
147a10cf76eSAxel Dörfler 
148a633251fSAlex Wilson 
149a10cf76eSAxel Dörfler void
150*7afc7756SAlex Wilson SettingsView::SetDefaultInput(const dormant_node_info* info)
151a10cf76eSAxel Dörfler {
152*7afc7756SAlex Wilson 	_ClearMenuSelection(fInputMenu);
153*7afc7756SAlex Wilson 	NodeMenuItem* item = _FindNodeItem(fInputMenu, info);
154*7afc7756SAlex Wilson 	if (item)
155a10cf76eSAxel Dörfler 		item->SetMarked(true);
156*7afc7756SAlex Wilson }
157*7afc7756SAlex Wilson 
158*7afc7756SAlex Wilson 
159*7afc7756SAlex Wilson void
160*7afc7756SAlex Wilson SettingsView::SetDefaultOutput(const dormant_node_info* info)
161*7afc7756SAlex Wilson {
162*7afc7756SAlex Wilson 	_ClearMenuSelection(fOutputMenu);
163*7afc7756SAlex Wilson 	NodeMenuItem* item = _FindNodeItem(fOutputMenu, info);
164*7afc7756SAlex Wilson 	if (item)
165*7afc7756SAlex Wilson 		item->SetMarked(true);
166*7afc7756SAlex Wilson }
167*7afc7756SAlex Wilson 
168*7afc7756SAlex Wilson 
169*7afc7756SAlex Wilson void
170*7afc7756SAlex Wilson SettingsView::MessageReceived(BMessage* message)
171*7afc7756SAlex Wilson {
172*7afc7756SAlex Wilson 	switch (message->what) {
173*7afc7756SAlex Wilson 		case MEDIA_DEFAULT_INPUT_CHANGE:
174*7afc7756SAlex Wilson 		{
175*7afc7756SAlex Wilson 			int32 index;
176*7afc7756SAlex Wilson 			if (message->FindInt32("index", &index)!=B_OK)
177*7afc7756SAlex Wilson 				break;
178*7afc7756SAlex Wilson 			NodeMenuItem* item
179*7afc7756SAlex Wilson 				= static_cast<NodeMenuItem*>(fInputMenu->ItemAt(index));
180*7afc7756SAlex Wilson 			SetDefaultInput(item->NodeInfo());
181*7afc7756SAlex Wilson 			RestartRequired(true);
182*7afc7756SAlex Wilson 		}
183*7afc7756SAlex Wilson 		case MEDIA_DEFAULT_OUTPUT_CHANGE:
184*7afc7756SAlex Wilson 		{
185*7afc7756SAlex Wilson 			int32 index;
186*7afc7756SAlex Wilson 			if (message->FindInt32("index", &index)!=B_OK)
187*7afc7756SAlex Wilson 				break;
188*7afc7756SAlex Wilson 			NodeMenuItem* item
189*7afc7756SAlex Wilson 				= static_cast<NodeMenuItem*>(fOutputMenu->ItemAt(index));
190*7afc7756SAlex Wilson 			SetDefaultOutput(item->NodeInfo());
191*7afc7756SAlex Wilson 			RestartRequired(true);
192*7afc7756SAlex Wilson 		}
193*7afc7756SAlex Wilson 		case ML_ENABLE_REAL_TIME:
194*7afc7756SAlex Wilson 		{
195*7afc7756SAlex Wilson 			uint32 flags = 0;
196*7afc7756SAlex Wilson 			if (message->FindUInt32("flags", &flags) == B_OK)
197*7afc7756SAlex Wilson 				_FlipRealtimeFlag(flags);
198a10cf76eSAxel Dörfler 			break;
199a10cf76eSAxel Dörfler 		}
200a10cf76eSAxel Dörfler 	}
201*7afc7756SAlex Wilson 	BGridView::MessageReceived(message);
202*7afc7756SAlex Wilson }
203a10cf76eSAxel Dörfler 
204a633251fSAlex Wilson 
205*7afc7756SAlex Wilson void
206*7afc7756SAlex Wilson SettingsView::AttachedToWindow()
207*7afc7756SAlex Wilson {
208*7afc7756SAlex Wilson 	BMessenger thisMessenger(this);
209*7afc7756SAlex Wilson 	fInputMenu->SetTargetForItems(thisMessenger);
210*7afc7756SAlex Wilson 	fOutputMenu->SetTargetForItems(thisMessenger);
211*7afc7756SAlex Wilson 	fRealtimeCheckBox->SetTarget(thisMessenger);
212*7afc7756SAlex Wilson }
213*7afc7756SAlex Wilson 
214*7afc7756SAlex Wilson 
215*7afc7756SAlex Wilson void
216*7afc7756SAlex Wilson SettingsView::RestartRequired(bool required)
217*7afc7756SAlex Wilson {
218*7afc7756SAlex Wilson 	if (required)
219*7afc7756SAlex Wilson 		fRestartView->Show();
220*7afc7756SAlex Wilson 	else
221*7afc7756SAlex Wilson 		fRestartView->Hide();
222*7afc7756SAlex Wilson }
223*7afc7756SAlex Wilson 
224*7afc7756SAlex Wilson 
225*7afc7756SAlex Wilson MediaWindow*
226*7afc7756SAlex Wilson SettingsView::_MediaWindow() const
227*7afc7756SAlex Wilson {
228*7afc7756SAlex Wilson 	return static_cast<MediaWindow*>(Window());
229*7afc7756SAlex Wilson }
230*7afc7756SAlex Wilson 
231*7afc7756SAlex Wilson 
232*7afc7756SAlex Wilson void
233*7afc7756SAlex Wilson SettingsView::_FlipRealtimeFlag(uint32 mask)
234*7afc7756SAlex Wilson {
235*7afc7756SAlex Wilson 	// TODO: error codes
236*7afc7756SAlex Wilson 	uint32 flags = 0;
237a10cf76eSAxel Dörfler 	BMediaRoster* roster = BMediaRoster::Roster();
238*7afc7756SAlex Wilson 	roster->GetRealtimeFlags(&flags);
239*7afc7756SAlex Wilson 	if (flags & mask)
240*7afc7756SAlex Wilson 		flags &= ~mask;
241*7afc7756SAlex Wilson 	else
242*7afc7756SAlex Wilson 		flags |= mask;
243*7afc7756SAlex Wilson 	roster->SetRealtimeFlags(flags);
244a633251fSAlex Wilson }
245a10cf76eSAxel Dörfler 
246a10cf76eSAxel Dörfler 
247*7afc7756SAlex Wilson void
248*7afc7756SAlex Wilson SettingsView::_EmptyMenu(BMenu* menu)
249*7afc7756SAlex Wilson {
250*7afc7756SAlex Wilson 	while (menu->CountItems() > 0)
251*7afc7756SAlex Wilson 		delete menu->RemoveItem((int32)0);
252*7afc7756SAlex Wilson }
253*7afc7756SAlex Wilson 
254*7afc7756SAlex Wilson 
255*7afc7756SAlex Wilson void
256*7afc7756SAlex Wilson SettingsView::_PopulateMenu(BMenu* menu, NodeList& nodes,
257*7afc7756SAlex Wilson 	const BMessage& message)
258*7afc7756SAlex Wilson {
259*7afc7756SAlex Wilson 	for (int32 i = 0; i < nodes.CountItems(); i++) {
260*7afc7756SAlex Wilson 		dormant_node_info* info = nodes.ItemAt(i);
261*7afc7756SAlex Wilson 		menu->AddItem(new NodeMenuItem(info, new BMessage(message)));
262*7afc7756SAlex Wilson 	}
263*7afc7756SAlex Wilson 
264*7afc7756SAlex Wilson 	if (Window() != NULL)
265*7afc7756SAlex Wilson 		menu->SetTargetForItems(BMessenger(this));
266*7afc7756SAlex Wilson }
267*7afc7756SAlex Wilson 
268*7afc7756SAlex Wilson 
269*7afc7756SAlex Wilson NodeMenuItem*
270*7afc7756SAlex Wilson SettingsView::_FindNodeItem(BMenu* menu, const dormant_node_info* nodeInfo)
271*7afc7756SAlex Wilson {
272*7afc7756SAlex Wilson 	for (int32 i = 0; i < menu->CountItems(); i++) {
273*7afc7756SAlex Wilson 		NodeMenuItem* item = static_cast<NodeMenuItem*>(menu->ItemAt(i));
274*7afc7756SAlex Wilson 		const dormant_node_info* itemInfo = item->NodeInfo();
275*7afc7756SAlex Wilson 		if (itemInfo && itemInfo->addon == nodeInfo->addon
276*7afc7756SAlex Wilson 			&& itemInfo->flavor_id == nodeInfo->flavor_id) {
277*7afc7756SAlex Wilson 			return item;
278a10cf76eSAxel Dörfler 		}
279a10cf76eSAxel Dörfler 	}
280*7afc7756SAlex Wilson 	return NULL;
281a10cf76eSAxel Dörfler }
282*7afc7756SAlex Wilson 
283*7afc7756SAlex Wilson 
284*7afc7756SAlex Wilson void
285*7afc7756SAlex Wilson SettingsView::_ClearMenuSelection(BMenu* menu)
286*7afc7756SAlex Wilson {
287*7afc7756SAlex Wilson 	for (int32 i = 0; i < menu->CountItems(); i++) {
288*7afc7756SAlex Wilson 		BMenuItem* item = menu->ItemAt(i);
289*7afc7756SAlex Wilson 		item->SetMarked(false);
290a10cf76eSAxel Dörfler 	}
291a10cf76eSAxel Dörfler }
292a10cf76eSAxel Dörfler 
293a633251fSAlex Wilson 
294*7afc7756SAlex Wilson NodeMenuItem::NodeMenuItem(const dormant_node_info* info, BMessage* message,
295a10cf76eSAxel Dörfler 	char shortcut, uint32 modifiers)
296a633251fSAlex Wilson 	:
297a633251fSAlex Wilson 	BMenuItem(info->name, message, shortcut, modifiers),
298b4a12470SJérôme Duval 	fInfo(info)
299a10cf76eSAxel Dörfler {
300a10cf76eSAxel Dörfler 
301a10cf76eSAxel Dörfler }
302a10cf76eSAxel Dörfler 
3036df0b2d5SJérôme Duval 
3046df0b2d5SJérôme Duval status_t
305*7afc7756SAlex Wilson NodeMenuItem::Invoke(BMessage* message)
3066df0b2d5SJérôme Duval {
3076df0b2d5SJérôme Duval 	if (IsMarked())
3086df0b2d5SJérôme Duval 		return B_OK;
3096df0b2d5SJérôme Duval 	return BMenuItem::Invoke(message);
3106df0b2d5SJérôme Duval }
3116df0b2d5SJérôme Duval 
3126df0b2d5SJérôme Duval 
313*7afc7756SAlex Wilson ChannelMenuItem::ChannelMenuItem(media_input* input, BMessage* message,
314*7afc7756SAlex Wilson 	char shortcut, uint32 modifiers)
315a633251fSAlex Wilson 	:
316a633251fSAlex Wilson 	BMenuItem(input->name, message, shortcut, modifiers),
317b4a12470SJérôme Duval 	fInput(input)
318a10cf76eSAxel Dörfler {
319a10cf76eSAxel Dörfler }
320a10cf76eSAxel Dörfler 
3216df0b2d5SJérôme Duval 
322*7afc7756SAlex Wilson ChannelMenuItem::~ChannelMenuItem()
323a10cf76eSAxel Dörfler {
324b4a12470SJérôme Duval 	delete fInput;
325a10cf76eSAxel Dörfler }
326a10cf76eSAxel Dörfler 
3276df0b2d5SJérôme Duval 
328*7afc7756SAlex Wilson int32
329*7afc7756SAlex Wilson ChannelMenuItem::DestinationID()
330*7afc7756SAlex Wilson {
331*7afc7756SAlex Wilson 	return fInput->destination.id;
332*7afc7756SAlex Wilson }
333*7afc7756SAlex Wilson 
334*7afc7756SAlex Wilson 
335*7afc7756SAlex Wilson media_input*
336*7afc7756SAlex Wilson ChannelMenuItem::Input()
337*7afc7756SAlex Wilson {
338*7afc7756SAlex Wilson 	return fInput;
339*7afc7756SAlex Wilson }
340*7afc7756SAlex Wilson 
341*7afc7756SAlex Wilson 
3426df0b2d5SJérôme Duval status_t
343*7afc7756SAlex Wilson ChannelMenuItem::Invoke(BMessage* message)
3446df0b2d5SJérôme Duval {
3456df0b2d5SJérôme Duval 	if (IsMarked())
3466df0b2d5SJérôme Duval 		return B_OK;
3476df0b2d5SJérôme Duval 	return BMenuItem::Invoke(message);
3486df0b2d5SJérôme Duval }
3496df0b2d5SJérôme Duval 
350*7afc7756SAlex Wilson 
351*7afc7756SAlex Wilson AudioSettingsView::AudioSettingsView()
352*7afc7756SAlex Wilson {
353*7afc7756SAlex Wilson 	BBox* defaultsBox = new BBox("defaults");
354*7afc7756SAlex Wilson 	defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
355*7afc7756SAlex Wilson 	BGridView* defaultsGridView = new BGridView();
356*7afc7756SAlex Wilson 
357*7afc7756SAlex Wilson 	BMenuField* inputMenuField = new BMenuField("inputMenuField",
358*7afc7756SAlex Wilson 		B_TRANSLATE("Audio input:"), InputMenu(), NULL);
359*7afc7756SAlex Wilson 
360*7afc7756SAlex Wilson 	BMenuField* outputMenuField = new BMenuField("outputMenuField",
361*7afc7756SAlex Wilson 		B_TRANSLATE("Audio output:"), OutputMenu(), NULL);
362*7afc7756SAlex Wilson 
363*7afc7756SAlex Wilson 	BLayoutBuilder::Grid<>(defaultsGridView)
364*7afc7756SAlex Wilson 		.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0)
365*7afc7756SAlex Wilson 		.AddMenuField(inputMenuField, 0, 0, B_ALIGN_HORIZONTAL_UNSET, 1, 3, 1)
366*7afc7756SAlex Wilson 		.AddMenuField(outputMenuField, 0, 1)
367*7afc7756SAlex Wilson 		.AddMenuField(_MakeChannelMenu(), 2, 1)
368*7afc7756SAlex Wilson 		.Add(MakeRestartMessageView(), 0, 2, 4, 1);
369*7afc7756SAlex Wilson 
370*7afc7756SAlex Wilson 	defaultsBox->AddChild(defaultsGridView);
371*7afc7756SAlex Wilson 
372*7afc7756SAlex Wilson 	const char* realtimeLabel = B_TRANSLATE("Enable real-time audio");
373*7afc7756SAlex Wilson 	const char* realtimeInfo = B_TRANSLATE(
374*7afc7756SAlex Wilson 		"Enabling real-time audio allows system to record and play audio "
375*7afc7756SAlex Wilson 		"as fast as possible.  It achieves this performance by using more"
376*7afc7756SAlex Wilson 		" CPU and RAM.\n\nOnly enable this feature if you need the lowest"
377*7afc7756SAlex Wilson 		" latency possible.");
378*7afc7756SAlex Wilson 
379*7afc7756SAlex Wilson 
380*7afc7756SAlex Wilson 	BLayoutBuilder::Grid<>(this)
381*7afc7756SAlex Wilson 		.SetInsets(0, 0, 0, 0)
382*7afc7756SAlex Wilson 		.Add(defaultsBox, 0, 0, 2, 1)
383*7afc7756SAlex Wilson 		.Add(MakeRealtimeBox(realtimeInfo, B_MEDIA_REALTIME_AUDIO,
384*7afc7756SAlex Wilson 			realtimeLabel), 0, 1, 2, 1)
385*7afc7756SAlex Wilson 		.Add(_MakeVolumeCheckBox(),0, 2, 1, 1)
386*7afc7756SAlex Wilson 		.Add(MakeRestartButton(), 1, 2, 1, 1)
387*7afc7756SAlex Wilson 		.SetRowWeight(1, 10);
388*7afc7756SAlex Wilson }
389*7afc7756SAlex Wilson 
390*7afc7756SAlex Wilson 
391*7afc7756SAlex Wilson void
392*7afc7756SAlex Wilson AudioSettingsView::SetDefaultChannel(int32 channelID)
393*7afc7756SAlex Wilson {
394*7afc7756SAlex Wilson 	for (int32 i = 0; i < fChannelMenu->CountItems(); i++) {
395*7afc7756SAlex Wilson 		ChannelMenuItem* item = _ChannelMenuItemAt(i);
396*7afc7756SAlex Wilson 		item->SetMarked(item->DestinationID() == channelID);
397*7afc7756SAlex Wilson 	}
398*7afc7756SAlex Wilson }
399*7afc7756SAlex Wilson 
400*7afc7756SAlex Wilson 
401*7afc7756SAlex Wilson void
402*7afc7756SAlex Wilson AudioSettingsView::AttachedToWindow()
403*7afc7756SAlex Wilson {
404*7afc7756SAlex Wilson 	SettingsView::AttachedToWindow();
405*7afc7756SAlex Wilson 
406*7afc7756SAlex Wilson 	BMessenger thisMessenger(this);
407*7afc7756SAlex Wilson 	fChannelMenu->SetTargetForItems(thisMessenger);
408*7afc7756SAlex Wilson 	fVolumeCheckBox->SetTarget(thisMessenger);
409*7afc7756SAlex Wilson }
410*7afc7756SAlex Wilson 
411*7afc7756SAlex Wilson 
412*7afc7756SAlex Wilson void
413*7afc7756SAlex Wilson AudioSettingsView::MessageReceived(BMessage* message)
414*7afc7756SAlex Wilson {
415*7afc7756SAlex Wilson 	switch (message->what) {
416*7afc7756SAlex Wilson 		case ML_DEFAULT_CHANNEL_CHANGED:
417*7afc7756SAlex Wilson 			{
418*7afc7756SAlex Wilson 				int32 index;
419*7afc7756SAlex Wilson 				if (message->FindInt32("index", &index) != B_OK)
420*7afc7756SAlex Wilson 					break;
421*7afc7756SAlex Wilson 				ChannelMenuItem* item = _ChannelMenuItemAt(index);
422*7afc7756SAlex Wilson 
423*7afc7756SAlex Wilson 				if (item) {
424*7afc7756SAlex Wilson 					BMediaRoster* roster = BMediaRoster::Roster();
425*7afc7756SAlex Wilson 					roster->SetAudioOutput(*item->Input());
426*7afc7756SAlex Wilson 					RestartRequired(true);
427*7afc7756SAlex Wilson 				} else
428*7afc7756SAlex Wilson 					fprintf(stderr, "ChannelMenuItem not found\n");
429*7afc7756SAlex Wilson 			}
430*7afc7756SAlex Wilson 			break;
431*7afc7756SAlex Wilson 		case MEDIA_SHOW_HIDE_VOLUME_CONTROL:
432*7afc7756SAlex Wilson 		{
433*7afc7756SAlex Wilson 			if (fVolumeCheckBox->Value() == B_CONTROL_ON)
434*7afc7756SAlex Wilson 				_ShowDeskbarVolumeControl();
435*7afc7756SAlex Wilson 			else
436*7afc7756SAlex Wilson 				_HideDeskbarVolumeControl();
437*7afc7756SAlex Wilson 			break;
438*7afc7756SAlex Wilson 		}
439*7afc7756SAlex Wilson 
440*7afc7756SAlex Wilson 		default:
441*7afc7756SAlex Wilson 			SettingsView::MessageReceived(message);
442*7afc7756SAlex Wilson 	}
443*7afc7756SAlex Wilson }
444*7afc7756SAlex Wilson 
445*7afc7756SAlex Wilson 
446*7afc7756SAlex Wilson void
447*7afc7756SAlex Wilson AudioSettingsView::SetDefaultInput(const dormant_node_info* info)
448*7afc7756SAlex Wilson {
449*7afc7756SAlex Wilson 	SettingsView::SetDefaultInput(info);
450*7afc7756SAlex Wilson 	_MediaWindow()->UpdateInputListItem(MediaListItem::AUDIO_TYPE, info);
451*7afc7756SAlex Wilson 	BMediaRoster::Roster()->SetAudioInput(*info);
452*7afc7756SAlex Wilson }
453*7afc7756SAlex Wilson 
454*7afc7756SAlex Wilson 
455*7afc7756SAlex Wilson void
456*7afc7756SAlex Wilson AudioSettingsView::SetDefaultOutput(const dormant_node_info* info)
457*7afc7756SAlex Wilson {
458*7afc7756SAlex Wilson 	SettingsView::SetDefaultOutput(info);
459*7afc7756SAlex Wilson 	_MediaWindow()->UpdateOutputListItem(MediaListItem::AUDIO_TYPE, info);
460*7afc7756SAlex Wilson 	_FillChannelMenu(info);
461*7afc7756SAlex Wilson 	BMediaRoster::Roster()->SetAudioOutput(*info);
462*7afc7756SAlex Wilson }
463*7afc7756SAlex Wilson 
464*7afc7756SAlex Wilson 
465*7afc7756SAlex Wilson BMenuField*
466*7afc7756SAlex Wilson AudioSettingsView::_MakeChannelMenu()
467*7afc7756SAlex Wilson {
468*7afc7756SAlex Wilson 	fChannelMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
469*7afc7756SAlex Wilson 	fChannelMenu->SetLabelFromMarked(true);
470*7afc7756SAlex Wilson 	BMenuField* channelMenuField = new BMenuField("channelMenuField",
471*7afc7756SAlex Wilson 		B_TRANSLATE("Channel:"), fChannelMenu, NULL);
472*7afc7756SAlex Wilson 	return channelMenuField;
473*7afc7756SAlex Wilson }
474*7afc7756SAlex Wilson 
475*7afc7756SAlex Wilson 
476*7afc7756SAlex Wilson BCheckBox*
477*7afc7756SAlex Wilson AudioSettingsView::_MakeVolumeCheckBox()
478*7afc7756SAlex Wilson {
479*7afc7756SAlex Wilson 	fVolumeCheckBox = new BCheckBox("volumeCheckBox",
480*7afc7756SAlex Wilson 		B_TRANSLATE("Show volume control on Deskbar"),
481*7afc7756SAlex Wilson 		new BMessage(MEDIA_SHOW_HIDE_VOLUME_CONTROL));
482*7afc7756SAlex Wilson 
483*7afc7756SAlex Wilson 	if (BDeskbar().HasItem("MediaReplicant"))
484*7afc7756SAlex Wilson 		fVolumeCheckBox->SetValue(B_CONTROL_ON);
485*7afc7756SAlex Wilson 
486*7afc7756SAlex Wilson 	return fVolumeCheckBox;
487*7afc7756SAlex Wilson }
488*7afc7756SAlex Wilson 
489*7afc7756SAlex Wilson 
490*7afc7756SAlex Wilson void
491*7afc7756SAlex Wilson AudioSettingsView::_FillChannelMenu(const dormant_node_info* nodeInfo)
492*7afc7756SAlex Wilson {
493*7afc7756SAlex Wilson 	_EmptyMenu(fChannelMenu);
494*7afc7756SAlex Wilson 
495*7afc7756SAlex Wilson 	BMediaRoster* roster = BMediaRoster::Roster();
496*7afc7756SAlex Wilson 	media_node node;
497*7afc7756SAlex Wilson 	media_node_id node_id;
498*7afc7756SAlex Wilson 
499*7afc7756SAlex Wilson 	status_t err = roster->GetInstancesFor(nodeInfo->addon,
500*7afc7756SAlex Wilson 		nodeInfo->flavor_id, &node_id);
501*7afc7756SAlex Wilson 	if (err != B_OK) {
502*7afc7756SAlex Wilson 		err = roster->InstantiateDormantNode(*nodeInfo, &node,
503*7afc7756SAlex Wilson 			B_FLAVOR_IS_GLOBAL);
504*7afc7756SAlex Wilson 	} else {
505*7afc7756SAlex Wilson 		err = roster->GetNodeFor(node_id, &node);
506*7afc7756SAlex Wilson 	}
507*7afc7756SAlex Wilson 
508*7afc7756SAlex Wilson 	if (err == B_OK) {
509*7afc7756SAlex Wilson 		int32 inputCount = 4;
510*7afc7756SAlex Wilson 		media_input* inputs = new media_input[inputCount];
511*7afc7756SAlex Wilson 		BPrivate::ArrayDeleter<media_input> inputDeleter(inputs);
512*7afc7756SAlex Wilson 
513*7afc7756SAlex Wilson 		while (true) {
514*7afc7756SAlex Wilson 			int32 realInputCount = 0;
515*7afc7756SAlex Wilson 			err = roster->GetAllInputsFor(node, inputs,
516*7afc7756SAlex Wilson 				inputCount, &realInputCount);
517*7afc7756SAlex Wilson 			if (realInputCount > inputCount) {
518*7afc7756SAlex Wilson 				inputCount *= 2;
519*7afc7756SAlex Wilson 				inputs = new media_input[inputCount];
520*7afc7756SAlex Wilson 				inputDeleter.SetTo(inputs);
521*7afc7756SAlex Wilson 			} else {
522*7afc7756SAlex Wilson 				inputCount = realInputCount;
523*7afc7756SAlex Wilson 				break;
524*7afc7756SAlex Wilson 			}
525*7afc7756SAlex Wilson 		}
526*7afc7756SAlex Wilson 
527*7afc7756SAlex Wilson 		if (err == B_OK) {
528*7afc7756SAlex Wilson 			BMessage message(ML_DEFAULT_CHANNEL_CHANGED);
529*7afc7756SAlex Wilson 
530*7afc7756SAlex Wilson 			for (int32 i = 0; i < inputCount; i++) {
531*7afc7756SAlex Wilson 				media_input* input = new media_input();
532*7afc7756SAlex Wilson 				memcpy(input, &inputs[i], sizeof(*input));
533*7afc7756SAlex Wilson 				ChannelMenuItem* channelItem = new ChannelMenuItem(input,
534*7afc7756SAlex Wilson 					new BMessage(message));
535*7afc7756SAlex Wilson 				fChannelMenu->AddItem(channelItem);
536*7afc7756SAlex Wilson 
537*7afc7756SAlex Wilson 				if (channelItem->DestinationID() == 0)
538*7afc7756SAlex Wilson 					channelItem->SetMarked(true);
539*7afc7756SAlex Wilson 			}
540*7afc7756SAlex Wilson 		}
541*7afc7756SAlex Wilson 	}
542*7afc7756SAlex Wilson 
543*7afc7756SAlex Wilson 	if (Window())
544*7afc7756SAlex Wilson 		fChannelMenu->SetTargetForItems(BMessenger(this));
545*7afc7756SAlex Wilson }
546*7afc7756SAlex Wilson 
547*7afc7756SAlex Wilson 
548*7afc7756SAlex Wilson void
549*7afc7756SAlex Wilson AudioSettingsView::_ShowDeskbarVolumeControl()
550*7afc7756SAlex Wilson {
551*7afc7756SAlex Wilson 	BDeskbar deskbar;
552*7afc7756SAlex Wilson 	BEntry entry("/bin/desklink", true);
553*7afc7756SAlex Wilson 	int32 id;
554*7afc7756SAlex Wilson 	entry_ref ref;
555*7afc7756SAlex Wilson 	status_t status = entry.GetRef(&ref);
556*7afc7756SAlex Wilson 	if (status == B_OK)
557*7afc7756SAlex Wilson 		status = deskbar.AddItem(&ref, &id);
558*7afc7756SAlex Wilson 
559*7afc7756SAlex Wilson 	if (status != B_OK) {
560*7afc7756SAlex Wilson 		fprintf(stderr, B_TRANSLATE(
561*7afc7756SAlex Wilson 			"Couldn't add volume control in Deskbar: %s\n"),
562*7afc7756SAlex Wilson 			strerror(status));
563*7afc7756SAlex Wilson 	}
564*7afc7756SAlex Wilson }
565*7afc7756SAlex Wilson 
566*7afc7756SAlex Wilson 
567*7afc7756SAlex Wilson void
568*7afc7756SAlex Wilson AudioSettingsView::_HideDeskbarVolumeControl()
569*7afc7756SAlex Wilson {
570*7afc7756SAlex Wilson 	BDeskbar deskbar;
571*7afc7756SAlex Wilson 	status_t status = deskbar.RemoveItem("MediaReplicant");
572*7afc7756SAlex Wilson 	if (status != B_OK) {
573*7afc7756SAlex Wilson 		fprintf(stderr, B_TRANSLATE(
574*7afc7756SAlex Wilson 			"Couldn't remove volume control in Deskbar: %s\n"),
575*7afc7756SAlex Wilson 			strerror(status));
576*7afc7756SAlex Wilson 	}
577*7afc7756SAlex Wilson }
578*7afc7756SAlex Wilson 
579*7afc7756SAlex Wilson 
580*7afc7756SAlex Wilson ChannelMenuItem*
581*7afc7756SAlex Wilson AudioSettingsView::_ChannelMenuItemAt(int32 index)
582*7afc7756SAlex Wilson {
583*7afc7756SAlex Wilson 	return static_cast<ChannelMenuItem*>(fChannelMenu->ItemAt(index));
584*7afc7756SAlex Wilson }
585*7afc7756SAlex Wilson 
586*7afc7756SAlex Wilson 
587*7afc7756SAlex Wilson VideoSettingsView::VideoSettingsView()
588*7afc7756SAlex Wilson {
589*7afc7756SAlex Wilson 	BBox* defaultsBox = new BBox("defaults");
590*7afc7756SAlex Wilson 	defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
591*7afc7756SAlex Wilson 	BGridView* defaultsGridView = new BGridView();
592*7afc7756SAlex Wilson 
593*7afc7756SAlex Wilson 	BMenuField* inputMenuField = new BMenuField("inputMenuField",
594*7afc7756SAlex Wilson 		B_TRANSLATE("Video input:"), InputMenu(), NULL);
595*7afc7756SAlex Wilson 
596*7afc7756SAlex Wilson 	BMenuField* outputMenuField = new BMenuField("outputMenuField",
597*7afc7756SAlex Wilson 		B_TRANSLATE("Video output:"), OutputMenu(), NULL);
598*7afc7756SAlex Wilson 
599*7afc7756SAlex Wilson 	BLayoutBuilder::Grid<>(defaultsGridView)
600*7afc7756SAlex Wilson 		.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0)
601*7afc7756SAlex Wilson 		.AddMenuField(inputMenuField, 0, 0)
602*7afc7756SAlex Wilson 		.AddMenuField(outputMenuField, 0, 1)
603*7afc7756SAlex Wilson 		.Add(MakeRestartMessageView(), 0, 2, 2, 1);
604*7afc7756SAlex Wilson 
605*7afc7756SAlex Wilson 	defaultsBox->AddChild(defaultsGridView);
606*7afc7756SAlex Wilson 
607*7afc7756SAlex Wilson 	const char* realtimeLabel = B_TRANSLATE("Enable real-time video");
608*7afc7756SAlex Wilson 	const char*	realtimeInfo = B_TRANSLATE(
609*7afc7756SAlex Wilson 		"Enabling real-time video allows system to "
610*7afc7756SAlex Wilson 		"perform video operations as fast and smoothly as possible.  It "
611*7afc7756SAlex Wilson 		"achieves optimum performance by using more RAM.\n\n"
612*7afc7756SAlex Wilson 		"Only enable this feature if you need the lowest latency possible.");
613*7afc7756SAlex Wilson 
614*7afc7756SAlex Wilson 	BLayoutBuilder::Grid<>(this)
615*7afc7756SAlex Wilson 		.SetInsets(0, 0, 0, 0)
616*7afc7756SAlex Wilson 		.Add(defaultsBox, 0, 0, 2, 1)
617*7afc7756SAlex Wilson 		.Add(MakeRealtimeBox(realtimeInfo, B_MEDIA_REALTIME_VIDEO,
618*7afc7756SAlex Wilson 			realtimeLabel), 0, 1, 2, 1)
619*7afc7756SAlex Wilson 		.Add(MakeRestartButton(), 1, 2, 1, 1)
620*7afc7756SAlex Wilson 		.SetRowWeight(1, 10);
621*7afc7756SAlex Wilson }
622*7afc7756SAlex Wilson 
623*7afc7756SAlex Wilson 
624*7afc7756SAlex Wilson void
625*7afc7756SAlex Wilson VideoSettingsView::SetDefaultInput(const dormant_node_info* info)
626*7afc7756SAlex Wilson {
627*7afc7756SAlex Wilson 	SettingsView::SetDefaultInput(info);
628*7afc7756SAlex Wilson 	_MediaWindow()->UpdateInputListItem(MediaListItem::VIDEO_TYPE, info);
629*7afc7756SAlex Wilson 	BMediaRoster::Roster()->SetVideoInput(*info);
630*7afc7756SAlex Wilson }
631*7afc7756SAlex Wilson 
632*7afc7756SAlex Wilson 
633*7afc7756SAlex Wilson void
634*7afc7756SAlex Wilson VideoSettingsView::SetDefaultOutput(const dormant_node_info* info)
635*7afc7756SAlex Wilson {
636*7afc7756SAlex Wilson 	SettingsView::SetDefaultOutput(info);
637*7afc7756SAlex Wilson 	_MediaWindow()->UpdateOutputListItem(MediaListItem::VIDEO_TYPE, info);
638*7afc7756SAlex Wilson 	BMediaRoster::Roster()->SetVideoOutput(*info);
639*7afc7756SAlex Wilson }
640