xref: /haiku/src/preferences/media/MediaViews.cpp (revision a7dde370f552f5376edbf25046ec9cf2ba8bbd1a)
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:        MediaViews.cpp
10 //  Author:      Sikosis, Jérôme Duval
11 //  Description: Media Preferences
12 //  Created :    June 25, 2003
13 //
14 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
15 
16 
17 #include "MediaViews.h"
18 
19 #include <Box.h>
20 #include <Button.h>
21 #include <Catalog.h>
22 #include <Deskbar.h>
23 #include <Entry.h>
24 #include <GroupView.h>
25 #include <Locale.h>
26 #include <MediaAddOn.h>
27 #include <MediaRoster.h>
28 #include <MenuField.h>
29 #include <PopUpMenu.h>
30 #include <SpaceLayoutItem.h>
31 #include <String.h>
32 #include <TextView.h>
33 
34 #include <stdio.h>
35 
36 
37 #undef B_TRANSLATE_CONTEXT
38 #define B_TRANSLATE_CONTEXT "Media views"
39 
40 
41 SettingsView::SettingsView (bool isVideo)
42 	:
43 	BView("SettingsView", B_WILL_DRAW | B_SUPPORTS_LAYOUT),
44 	fIsVideo(isVideo)
45 {
46 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
47 
48 	BBox* defaultsBox = new BBox("defaults");
49 	defaultsBox->SetLabel(fIsVideo ? B_TRANSLATE("Default nodes")
50 		: B_TRANSLATE("Defaults"));
51 
52 	// create the default box
53 	BGroupLayout* defaultBoxLayout = new BGroupLayout(B_VERTICAL, 5);
54 	defaultBoxLayout->SetInsets(10,10,10,10);
55 	defaultsBox->SetLayout(defaultBoxLayout);
56 	defaultBoxLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(5));
57 
58 	BGroupView* inputField = new BGroupView(B_HORIZONTAL);
59 	BGroupView* outputField = new BGroupView(B_HORIZONTAL);
60 	defaultsBox->GetLayout()->AddView(inputField);
61 	defaultsBox->GetLayout()->AddView(outputField);
62 
63 	float divider = StringWidth(fIsVideo ? B_TRANSLATE("Video output:")
64 		: B_TRANSLATE("Audio output:")) + 5;
65 	fMenu1 = new BPopUpMenu(B_TRANSLATE("<none>"));
66 	fMenu1->SetLabelFromMarked(true);
67 	BMenuField* menuField1 = new BMenuField("menuField1",
68 		fIsVideo ? B_TRANSLATE("Video input:")
69 			: B_TRANSLATE("Audio input:"), fMenu1, NULL);
70 	menuField1->SetDivider(divider);
71 
72 	fMenu2 = new BPopUpMenu(B_TRANSLATE("<none>"));
73 	fMenu2->SetLabelFromMarked(true);
74 	BMenuField* menuField2 = new BMenuField("menuField2",
75 		fIsVideo ? B_TRANSLATE("Video output:")
76 			: B_TRANSLATE("Audio output:"), fMenu2, NULL);
77 	menuField2->SetDivider(divider);
78 
79 	inputField->GroupLayout()->AddView(menuField1);
80 	outputField->GroupLayout()->AddView(menuField2);
81 
82 	BMenuField* menuField3 = NULL;
83 	if (!fIsVideo) {
84 		fMenu3 = new BPopUpMenu(B_TRANSLATE("<none>"));
85 		fMenu3->SetLabelFromMarked(true);
86 		menuField3 = new BMenuField("menuField3",
87 			B_TRANSLATE("Channel:"), fMenu3, NULL);
88 		outputField->GroupLayout()->AddView(menuField3);
89 		menuField3->SetDivider(StringWidth(B_TRANSLATE("Channel:"))+5);
90 	}
91 
92 	rgb_color red_color = {222, 32, 33};
93 	fRestartView = new BStringView("restartStringView",
94 		B_TRANSLATE("Restart the media server to apply changes."));
95 	fRestartView->SetHighColor(red_color);
96 	defaultsBox->AddChild(fRestartView);
97 	fRestartView->Hide();
98 
99 	// create the realtime box
100 	BBox* realtimeBox = new BBox("realtime");
101 	realtimeBox->SetLabel(B_TRANSLATE("Real-time"));
102 
103 	BMessage* message = new BMessage(ML_ENABLE_REAL_TIME);
104 	message->AddBool("isVideo", fIsVideo);
105 	fRealtimeCheckBox = new BCheckBox("realtimeCheckBox",
106 		fIsVideo ? B_TRANSLATE("Enable real-time video")
107 			: B_TRANSLATE("Enable real-time audio"),
108 		message);
109 
110 	uint32 flags;
111 	BMediaRoster::Roster()->GetRealtimeFlags(&flags);
112 	if (flags & (fIsVideo ? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO))
113 		fRealtimeCheckBox->SetValue(B_CONTROL_ON);
114 
115 	BTextView* textView = new BTextView("stringView");
116 	textView->Insert(fIsVideo ? B_TRANSLATE(
117 		"Enabling real-time video allows system to "
118 		"perform video operations as fast and smoothly as possible.  It "
119 		"achieves optimum performance by using more RAM."
120 		"\n\nOnly enable this feature if you need the lowest latency possible.")
121 		: B_TRANSLATE(
122 		"Enabling real-time audio allows system to record and play audio "
123 		"as fast as possible.  It achieves this performance by using more"
124 		" CPU and RAM.\n\nOnly enable this feature if you need the lowest"
125 		" latency possible."));
126 
127 	textView->MakeEditable(false);
128 	textView->MakeSelectable(false);
129 	textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
130 
131 	BGroupLayout* realtimeBoxLayout = new BGroupLayout(B_VERTICAL, 5);
132 	realtimeBoxLayout->SetInsets(10,10,10,10);
133 	realtimeBox->SetLayout(realtimeBoxLayout);
134 
135 	realtimeBoxLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(5));
136 	realtimeBoxLayout->AddView(fRealtimeCheckBox);
137 	realtimeBoxLayout->AddView(textView);
138 
139 	// create the bottom line: volumen in deskbar checkbox and restart button
140 	BGroupView* bottomView = new BGroupView(B_HORIZONTAL);
141 	BButton* restartButton = new BButton("restartButton",
142 		B_TRANSLATE("Restart media services"),
143 		new BMessage(ML_RESTART_MEDIA_SERVER));
144 
145 	if (!fIsVideo) {
146 		fVolumeCheckBox = new BCheckBox("volumeCheckBox",
147 			B_TRANSLATE("Show volume control on Deskbar"),
148 			new BMessage(ML_SHOW_VOLUME_CONTROL));
149 		bottomView->GroupLayout()->AddView(fVolumeCheckBox);
150 		if (BDeskbar().HasItem("MediaReplicant"))
151 			fVolumeCheckBox->SetValue(B_CONTROL_ON);
152 	}
153 	else{
154 		bottomView->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
155 	}
156 	bottomView->GroupLayout()->AddView(restartButton);
157 
158 	// compose all stuff
159 	BGroupLayout* rootlayout = new BGroupLayout(B_VERTICAL, 5);
160 	SetLayout(rootlayout);
161 
162 	rootlayout->AddView(defaultsBox);
163 	rootlayout->AddView(realtimeBox);
164 	rootlayout->AddView(bottomView);
165 }
166 
167 
168 void
169 SettingsView::AddNodes(NodeList& list, bool isInput)
170 {
171 	BMenu* menu = isInput ? fMenu1 : fMenu2;
172 	void* item;
173 	while ((item = menu->RemoveItem((int32)0)) != NULL)
174 		delete static_cast<dormant_node_info*>(item);
175 
176 	BMessage message(ML_DEFAULT_CHANGE);
177 	message.AddBool("isVideo", fIsVideo);
178 	message.AddBool("isInput", isInput);
179 
180 	for (int32 i = 0; i < list.CountItems(); i++) {
181 		dormant_node_info* info = list.ItemAt(i);
182 		menu->AddItem(new SettingsItem(info, new BMessage(message)));
183 	}
184 }
185 
186 
187 void
188 SettingsView::SetDefault(dormant_node_info &info, bool isInput, int32 outputID)
189 {
190 	BMenu* menu = isInput ? fMenu1 : fMenu2;
191 
192 	for (int32 i = 0; i < menu->CountItems(); i++) {
193 		SettingsItem* item = static_cast<SettingsItem*>(menu->ItemAt(i));
194 		if (item->fInfo && item->fInfo->addon == info.addon
195 			&& item->fInfo->flavor_id == info.flavor_id) {
196 			item->SetMarked(true);
197 			break;
198 		}
199 	}
200 
201 	if (!fIsVideo && !isInput && outputID >= 0) {
202 		BMenuItem* item;
203 		while ((item = fMenu3->RemoveItem((int32)0)) != NULL)
204 			delete item;
205 
206 		BMediaRoster* roster = BMediaRoster::Roster();
207 		media_node node;
208 		media_node_id node_id;
209 		status_t err;
210 		if (roster->GetInstancesFor(info.addon, info.flavor_id,
211 			&node_id) != B_OK) {
212 			err = roster->InstantiateDormantNode(info, &node,
213 				B_FLAVOR_IS_GLOBAL);
214 		} else {
215 			err = roster->GetNodeFor(node_id, &node);
216 		}
217 
218 		if (err == B_OK) {
219 			media_input inputs[16];
220 			int32 inputCount = 16;
221 			if (roster->GetAllInputsFor(node, inputs, 16, &inputCount)==B_OK) {
222 				BMessage message(ML_DEFAULTOUTPUT_CHANGE);
223 
224 				for (int32 i = 0; i < inputCount; i++) {
225 					media_input* input = new media_input();
226 					memcpy(input, &inputs[i], sizeof(*input));
227 					item = new Settings2Item(&info, input,
228 						new BMessage(message));
229 					fMenu3->AddItem(item);
230 					if (inputs[i].destination.id == outputID)
231 						item->SetMarked(true);
232 				}
233 			}
234 		}
235 	}
236 }
237 
238 
239 SettingsItem::SettingsItem(dormant_node_info* info, BMessage* message,
240 		char shortcut, uint32 modifiers)
241 	:
242 	BMenuItem(info->name, message, shortcut, modifiers),
243 	fInfo(info)
244 {
245 
246 }
247 
248 
249 status_t
250 SettingsItem::Invoke(BMessage* message)
251 {
252 	if (IsMarked())
253 		return B_OK;
254 	return BMenuItem::Invoke(message);
255 }
256 
257 
258 Settings2Item::Settings2Item(dormant_node_info* info, media_input* input,
259 		BMessage* message, char shortcut, uint32 modifiers)
260 	:
261 	BMenuItem(input->name, message, shortcut, modifiers),
262 	fInfo(info),
263 	fInput(input)
264 {
265 }
266 
267 
268 Settings2Item::~Settings2Item()
269 {
270 	delete fInput;
271 }
272 
273 
274 status_t
275 Settings2Item::Invoke(BMessage* message)
276 {
277 	if (IsMarked())
278 		return B_OK;
279 	return BMenuItem::Invoke(message);
280 }
281 
282