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