Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / preferences / media / MediaViews.cpp
blob87e869679e7be37efc2474f1bb13520ea2b18fc2
1 /*
2 * Copyright 2003-2011, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Sikosis
7 * Jérôme Duval
8 */
11 #include "MediaViews.h"
13 #include <AutoDeleter.h>
14 #include <Box.h>
15 #include <Button.h>
16 #include <Catalog.h>
17 #include <CheckBox.h>
18 #include <Deskbar.h>
19 #include <Entry.h>
20 #include <LayoutBuilder.h>
21 #include <Locale.h>
22 #include <MediaAddOn.h>
23 #include <MediaRoster.h>
24 #include <MenuField.h>
25 #include <PopUpMenu.h>
26 #include <String.h>
27 #include <StringView.h>
28 #include <TextView.h>
30 #include <assert.h>
31 #include <stdio.h>
33 #include "MediaWindow.h"
36 #undef B_TRANSLATION_CONTEXT
37 #define B_TRANSLATION_CONTEXT "Media views"
39 #define MEDIA_DEFAULT_INPUT_CHANGE 'dich'
40 #define MEDIA_DEFAULT_OUTPUT_CHANGE 'doch'
41 #define MEDIA_SHOW_HIDE_VOLUME_CONTROL 'shvc'
44 SettingsView::SettingsView()
46 BGroupView(B_VERTICAL, B_USE_DEFAULT_SPACING),
47 fInputMenu(NULL),
48 fOutputMenu(NULL)
50 // input menu
51 fInputMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
52 fInputMenu->SetLabelFromMarked(true);
54 // input menu
55 fOutputMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
56 fOutputMenu->SetLabelFromMarked(true);
60 BButton*
61 SettingsView::MakeRestartButton()
63 return new BButton("restartButton",
64 B_TRANSLATE("Restart media services"),
65 new BMessage(ML_RESTART_MEDIA_SERVER),
66 B_ALIGN_RIGHT);
71 void
72 SettingsView::AddInputNodes(NodeList& list)
74 _EmptyMenu(fInputMenu);
76 BMessage message(MEDIA_DEFAULT_INPUT_CHANGE);
77 _PopulateMenu(fInputMenu, list, message);
81 void
82 SettingsView::AddOutputNodes(NodeList& list)
84 _EmptyMenu(fOutputMenu);
86 BMessage message(MEDIA_DEFAULT_OUTPUT_CHANGE);
87 _PopulateMenu(fOutputMenu, list, message);
91 void
92 SettingsView::SetDefaultInput(const dormant_node_info* info)
94 _ClearMenuSelection(fInputMenu);
95 NodeMenuItem* item = _FindNodeItem(fInputMenu, info);
96 if (item)
97 item->SetMarked(true);
101 void
102 SettingsView::SetDefaultOutput(const dormant_node_info* info)
104 _ClearMenuSelection(fOutputMenu);
105 NodeMenuItem* item = _FindNodeItem(fOutputMenu, info);
106 if (item)
107 item->SetMarked(true);
111 void
112 SettingsView::MessageReceived(BMessage* message)
114 switch (message->what) {
115 case MEDIA_DEFAULT_INPUT_CHANGE:
117 int32 index;
118 if (message->FindInt32("index", &index)!=B_OK)
119 break;
120 NodeMenuItem* item
121 = static_cast<NodeMenuItem*>(fInputMenu->ItemAt(index));
122 SetDefaultInput(item->NodeInfo());
123 break;
125 case MEDIA_DEFAULT_OUTPUT_CHANGE:
127 int32 index;
128 if (message->FindInt32("index", &index)!=B_OK)
129 break;
130 NodeMenuItem* item
131 = static_cast<NodeMenuItem*>(fOutputMenu->ItemAt(index));
132 SetDefaultOutput(item->NodeInfo());
133 break;
135 default:
136 BGroupView::MessageReceived(message);
141 void
142 SettingsView::AttachedToWindow()
144 BMessenger thisMessenger(this);
145 fInputMenu->SetTargetForItems(thisMessenger);
146 fOutputMenu->SetTargetForItems(thisMessenger);
150 MediaWindow*
151 SettingsView::_MediaWindow() const
153 return static_cast<MediaWindow*>(Window());
157 void
158 SettingsView::_EmptyMenu(BMenu* menu)
160 while (menu->CountItems() > 0)
161 delete menu->RemoveItem((int32)0);
165 void
166 SettingsView::_PopulateMenu(BMenu* menu, NodeList& nodes,
167 const BMessage& message)
169 for (int32 i = 0; i < nodes.CountItems(); i++) {
170 dormant_node_info* info = nodes.ItemAt(i);
171 menu->AddItem(new NodeMenuItem(info, new BMessage(message)));
174 if (Window() != NULL)
175 menu->SetTargetForItems(BMessenger(this));
179 NodeMenuItem*
180 SettingsView::_FindNodeItem(BMenu* menu, const dormant_node_info* nodeInfo)
182 for (int32 i = 0; i < menu->CountItems(); i++) {
183 NodeMenuItem* item = static_cast<NodeMenuItem*>(menu->ItemAt(i));
184 const dormant_node_info* itemInfo = item->NodeInfo();
185 if (itemInfo && itemInfo->addon == nodeInfo->addon
186 && itemInfo->flavor_id == nodeInfo->flavor_id) {
187 return item;
190 return NULL;
194 void
195 SettingsView::_ClearMenuSelection(BMenu* menu)
197 for (int32 i = 0; i < menu->CountItems(); i++) {
198 BMenuItem* item = menu->ItemAt(i);
199 item->SetMarked(false);
204 NodeMenuItem::NodeMenuItem(const dormant_node_info* info, BMessage* message,
205 char shortcut, uint32 modifiers)
207 BMenuItem(info->name, message, shortcut, modifiers),
208 fInfo(info)
214 status_t
215 NodeMenuItem::Invoke(BMessage* message)
217 if (IsMarked())
218 return B_OK;
219 return BMenuItem::Invoke(message);
223 ChannelMenuItem::ChannelMenuItem(media_input* input, BMessage* message,
224 char shortcut, uint32 modifiers)
226 BMenuItem(input->name, message, shortcut, modifiers),
227 fInput(input)
232 ChannelMenuItem::~ChannelMenuItem()
234 delete fInput;
238 int32
239 ChannelMenuItem::DestinationID()
241 return fInput->destination.id;
245 media_input*
246 ChannelMenuItem::Input()
248 return fInput;
252 status_t
253 ChannelMenuItem::Invoke(BMessage* message)
255 if (IsMarked())
256 return B_OK;
257 return BMenuItem::Invoke(message);
261 AudioSettingsView::AudioSettingsView()
263 BBox* defaultsBox = new BBox("defaults");
264 defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
265 BGridView* defaultsGridView = new BGridView();
267 BMenuField* inputMenuField = new BMenuField("inputMenuField",
268 B_TRANSLATE("Audio input:"), InputMenu());
270 BMenuField* outputMenuField = new BMenuField("outputMenuField",
271 B_TRANSLATE("Audio output:"), OutputMenu());
273 BLayoutBuilder::Grid<>(defaultsGridView)
274 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
275 B_USE_DEFAULT_SPACING)
276 .AddMenuField(inputMenuField, 0, 0, B_ALIGN_HORIZONTAL_UNSET, 1, 3, 1)
277 .AddMenuField(outputMenuField, 0, 1)
278 .AddMenuField(_MakeChannelMenu(), 2, 1);
280 defaultsBox->AddChild(defaultsGridView);
282 BLayoutBuilder::Group<>(this)
283 .SetInsets(0, 0, 0, 0)
284 .Add(defaultsBox)
285 .AddGroup(B_HORIZONTAL)
286 .Add(_MakeVolumeCheckBox())
287 .Add(MakeRestartButton())
288 .End()
289 .AddGlue();
293 void
294 AudioSettingsView::SetDefaultChannel(int32 channelID)
296 for (int32 i = 0; i < fChannelMenu->CountItems(); i++) {
297 ChannelMenuItem* item = _ChannelMenuItemAt(i);
298 item->SetMarked(item->DestinationID() == channelID);
303 void
304 AudioSettingsView::AttachedToWindow()
306 SettingsView::AttachedToWindow();
308 BMessenger thisMessenger(this);
309 fChannelMenu->SetTargetForItems(thisMessenger);
310 fVolumeCheckBox->SetTarget(thisMessenger);
314 void
315 AudioSettingsView::MessageReceived(BMessage* message)
317 switch (message->what) {
318 case ML_DEFAULT_CHANNEL_CHANGED:
320 int32 index;
321 if (message->FindInt32("index", &index) != B_OK)
322 break;
323 ChannelMenuItem* item = _ChannelMenuItemAt(index);
325 if (item) {
326 BMediaRoster* roster = BMediaRoster::Roster();
327 roster->SetAudioOutput(*item->Input());
328 } else
329 fprintf(stderr, "ChannelMenuItem not found\n");
331 break;
332 case MEDIA_SHOW_HIDE_VOLUME_CONTROL:
334 if (fVolumeCheckBox->Value() == B_CONTROL_ON)
335 _ShowDeskbarVolumeControl();
336 else
337 _HideDeskbarVolumeControl();
338 break;
341 default:
342 SettingsView::MessageReceived(message);
347 void
348 AudioSettingsView::SetDefaultInput(const dormant_node_info* info)
350 SettingsView::SetDefaultInput(info);
351 _MediaWindow()->UpdateInputListItem(MediaListItem::AUDIO_TYPE, info);
352 BMediaRoster::Roster()->SetAudioInput(*info);
356 void
357 AudioSettingsView::SetDefaultOutput(const dormant_node_info* info)
359 SettingsView::SetDefaultOutput(info);
360 _MediaWindow()->UpdateOutputListItem(MediaListItem::AUDIO_TYPE, info);
361 _FillChannelMenu(info);
362 BMediaRoster::Roster()->SetAudioOutput(*info);
366 BMenuField*
367 AudioSettingsView::_MakeChannelMenu()
369 fChannelMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
370 fChannelMenu->SetLabelFromMarked(true);
371 BMenuField* channelMenuField = new BMenuField("channelMenuField",
372 B_TRANSLATE("Channel:"), fChannelMenu);
373 return channelMenuField;
377 BCheckBox*
378 AudioSettingsView::_MakeVolumeCheckBox()
380 fVolumeCheckBox = new BCheckBox("volumeCheckBox",
381 B_TRANSLATE("Show volume control on Deskbar"),
382 new BMessage(MEDIA_SHOW_HIDE_VOLUME_CONTROL));
384 if (BDeskbar().HasItem("MediaReplicant"))
385 fVolumeCheckBox->SetValue(B_CONTROL_ON);
387 return fVolumeCheckBox;
391 void
392 AudioSettingsView::_FillChannelMenu(const dormant_node_info* nodeInfo)
394 _EmptyMenu(fChannelMenu);
396 BMediaRoster* roster = BMediaRoster::Roster();
397 media_node node;
398 media_node_id node_id;
400 status_t err = roster->GetInstancesFor(nodeInfo->addon,
401 nodeInfo->flavor_id, &node_id);
402 if (err != B_OK) {
403 err = roster->InstantiateDormantNode(*nodeInfo, &node,
404 B_FLAVOR_IS_GLOBAL);
405 } else {
406 err = roster->GetNodeFor(node_id, &node);
409 if (err == B_OK) {
410 int32 inputCount = 4;
411 media_input* inputs = new media_input[inputCount];
412 BPrivate::ArrayDeleter<media_input> inputDeleter(inputs);
414 while (true) {
415 int32 realInputCount = 0;
416 err = roster->GetAllInputsFor(node, inputs,
417 inputCount, &realInputCount);
418 if (realInputCount > inputCount) {
419 inputCount *= 2;
420 inputs = new media_input[inputCount];
421 inputDeleter.SetTo(inputs);
422 } else {
423 inputCount = realInputCount;
424 break;
428 if (err == B_OK) {
429 BMessage message(ML_DEFAULT_CHANNEL_CHANGED);
431 for (int32 i = 0; i < inputCount; i++) {
432 media_input* input = new media_input();
433 memcpy(input, &inputs[i], sizeof(*input));
434 ChannelMenuItem* channelItem = new ChannelMenuItem(input,
435 new BMessage(message));
436 fChannelMenu->AddItem(channelItem);
438 if (channelItem->DestinationID() == 0)
439 channelItem->SetMarked(true);
444 if (Window())
445 fChannelMenu->SetTargetForItems(BMessenger(this));
449 void
450 AudioSettingsView::_ShowDeskbarVolumeControl()
452 BDeskbar deskbar;
453 BEntry entry("/bin/desklink", true);
454 int32 id;
455 entry_ref ref;
456 status_t status = entry.GetRef(&ref);
457 if (status == B_OK)
458 status = deskbar.AddItem(&ref, &id);
460 if (status != B_OK) {
461 fprintf(stderr, B_TRANSLATE(
462 "Couldn't add volume control in Deskbar: %s\n"),
463 strerror(status));
468 void
469 AudioSettingsView::_HideDeskbarVolumeControl()
471 BDeskbar deskbar;
472 status_t status = deskbar.RemoveItem("MediaReplicant");
473 if (status != B_OK) {
474 fprintf(stderr, B_TRANSLATE(
475 "Couldn't remove volume control in Deskbar: %s\n"),
476 strerror(status));
481 ChannelMenuItem*
482 AudioSettingsView::_ChannelMenuItemAt(int32 index)
484 return static_cast<ChannelMenuItem*>(fChannelMenu->ItemAt(index));
488 VideoSettingsView::VideoSettingsView()
490 BBox* defaultsBox = new BBox("defaults");
491 defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
492 BGridView* defaultsGridView = new BGridView();
494 BMenuField* inputMenuField = new BMenuField("inputMenuField",
495 B_TRANSLATE("Video input:"), InputMenu());
497 BMenuField* outputMenuField = new BMenuField("outputMenuField",
498 B_TRANSLATE("Video output:"), OutputMenu());
500 BLayoutBuilder::Grid<>(defaultsGridView)
501 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
502 B_USE_DEFAULT_SPACING)
503 .AddMenuField(inputMenuField, 0, 0)
504 .AddMenuField(outputMenuField, 0, 1);
506 defaultsBox->AddChild(defaultsGridView);
508 BLayoutBuilder::Group<>(this)
509 .SetInsets(0, 0, 0, 0)
510 .Add(defaultsBox)
511 .AddGroup(B_HORIZONTAL)
512 .AddGlue()
513 .Add(MakeRestartButton())
514 .End()
515 .AddGlue();
519 void
520 VideoSettingsView::SetDefaultInput(const dormant_node_info* info)
522 SettingsView::SetDefaultInput(info);
523 _MediaWindow()->UpdateInputListItem(MediaListItem::VIDEO_TYPE, info);
524 BMediaRoster::Roster()->SetVideoInput(*info);
528 void
529 VideoSettingsView::SetDefaultOutput(const dormant_node_info* info)
531 SettingsView::SetDefaultOutput(info);
532 _MediaWindow()->UpdateOutputListItem(MediaListItem::VIDEO_TYPE, info);
533 BMediaRoster::Roster()->SetVideoOutput(*info);