usb_ecm: Use the current configuration instead of a fixed one.
[haiku.git] / src / preferences / media / MediaViews.cpp
blobf8bb697ef8828ea71e86de6f44fb4e3cf3c7e50f
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 .AddGlue()
288 .Add(MakeRestartButton())
289 .End()
290 .AddGlue();
294 void
295 AudioSettingsView::SetDefaultChannel(int32 channelID)
297 for (int32 i = 0; i < fChannelMenu->CountItems(); i++) {
298 ChannelMenuItem* item = _ChannelMenuItemAt(i);
299 item->SetMarked(item->DestinationID() == channelID);
304 void
305 AudioSettingsView::AttachedToWindow()
307 SettingsView::AttachedToWindow();
309 BMessenger thisMessenger(this);
310 fChannelMenu->SetTargetForItems(thisMessenger);
311 fVolumeCheckBox->SetTarget(thisMessenger);
315 void
316 AudioSettingsView::MessageReceived(BMessage* message)
318 switch (message->what) {
319 case ML_DEFAULT_CHANNEL_CHANGED:
321 int32 index;
322 if (message->FindInt32("index", &index) != B_OK)
323 break;
324 ChannelMenuItem* item = _ChannelMenuItemAt(index);
326 if (item) {
327 BMediaRoster* roster = BMediaRoster::Roster();
328 roster->SetAudioOutput(*item->Input());
329 } else
330 fprintf(stderr, "ChannelMenuItem not found\n");
332 break;
333 case MEDIA_SHOW_HIDE_VOLUME_CONTROL:
335 if (fVolumeCheckBox->Value() == B_CONTROL_ON)
336 _ShowDeskbarVolumeControl();
337 else
338 _HideDeskbarVolumeControl();
339 break;
342 default:
343 SettingsView::MessageReceived(message);
348 void
349 AudioSettingsView::SetDefaultInput(const dormant_node_info* info)
351 SettingsView::SetDefaultInput(info);
352 _MediaWindow()->UpdateInputListItem(MediaListItem::AUDIO_TYPE, info);
353 BMediaRoster::Roster()->SetAudioInput(*info);
357 void
358 AudioSettingsView::SetDefaultOutput(const dormant_node_info* info)
360 SettingsView::SetDefaultOutput(info);
361 _MediaWindow()->UpdateOutputListItem(MediaListItem::AUDIO_TYPE, info);
362 _FillChannelMenu(info);
363 BMediaRoster::Roster()->SetAudioOutput(*info);
367 BMenuField*
368 AudioSettingsView::_MakeChannelMenu()
370 fChannelMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
371 fChannelMenu->SetLabelFromMarked(true);
372 BMenuField* channelMenuField = new BMenuField("channelMenuField",
373 B_TRANSLATE("Channel:"), fChannelMenu);
374 return channelMenuField;
378 BCheckBox*
379 AudioSettingsView::_MakeVolumeCheckBox()
381 fVolumeCheckBox = new BCheckBox("volumeCheckBox",
382 B_TRANSLATE("Show volume control on Deskbar"),
383 new BMessage(MEDIA_SHOW_HIDE_VOLUME_CONTROL));
385 if (BDeskbar().HasItem("MediaReplicant"))
386 fVolumeCheckBox->SetValue(B_CONTROL_ON);
388 return fVolumeCheckBox;
392 void
393 AudioSettingsView::_FillChannelMenu(const dormant_node_info* nodeInfo)
395 _EmptyMenu(fChannelMenu);
397 BMediaRoster* roster = BMediaRoster::Roster();
398 media_node node;
399 media_node_id node_id;
401 status_t err = roster->GetInstancesFor(nodeInfo->addon,
402 nodeInfo->flavor_id, &node_id);
403 if (err != B_OK) {
404 err = roster->InstantiateDormantNode(*nodeInfo, &node,
405 B_FLAVOR_IS_GLOBAL);
406 } else {
407 err = roster->GetNodeFor(node_id, &node);
410 if (err == B_OK) {
411 int32 inputCount = 4;
412 media_input* inputs = new media_input[inputCount];
413 BPrivate::ArrayDeleter<media_input> inputDeleter(inputs);
415 while (true) {
416 int32 realInputCount = 0;
417 err = roster->GetAllInputsFor(node, inputs,
418 inputCount, &realInputCount);
419 if (realInputCount > inputCount) {
420 inputCount *= 2;
421 inputs = new media_input[inputCount];
422 inputDeleter.SetTo(inputs);
423 } else {
424 inputCount = realInputCount;
425 break;
429 if (err == B_OK) {
430 BMessage message(ML_DEFAULT_CHANNEL_CHANGED);
432 for (int32 i = 0; i < inputCount; i++) {
433 media_input* input = new media_input();
434 memcpy(input, &inputs[i], sizeof(*input));
435 ChannelMenuItem* channelItem = new ChannelMenuItem(input,
436 new BMessage(message));
437 fChannelMenu->AddItem(channelItem);
439 if (channelItem->DestinationID() == 0)
440 channelItem->SetMarked(true);
445 if (Window())
446 fChannelMenu->SetTargetForItems(BMessenger(this));
450 void
451 AudioSettingsView::_ShowDeskbarVolumeControl()
453 BDeskbar deskbar;
454 BEntry entry("/bin/desklink", true);
455 int32 id;
456 entry_ref ref;
457 status_t status = entry.GetRef(&ref);
458 if (status == B_OK)
459 status = deskbar.AddItem(&ref, &id);
461 if (status != B_OK) {
462 fprintf(stderr, B_TRANSLATE(
463 "Couldn't add volume control in Deskbar: %s\n"),
464 strerror(status));
469 void
470 AudioSettingsView::_HideDeskbarVolumeControl()
472 BDeskbar deskbar;
473 status_t status = deskbar.RemoveItem("MediaReplicant");
474 if (status != B_OK) {
475 fprintf(stderr, B_TRANSLATE(
476 "Couldn't remove volume control in Deskbar: %s\n"),
477 strerror(status));
482 ChannelMenuItem*
483 AudioSettingsView::_ChannelMenuItemAt(int32 index)
485 return static_cast<ChannelMenuItem*>(fChannelMenu->ItemAt(index));
489 VideoSettingsView::VideoSettingsView()
491 BBox* defaultsBox = new BBox("defaults");
492 defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
493 BGridView* defaultsGridView = new BGridView();
495 BMenuField* inputMenuField = new BMenuField("inputMenuField",
496 B_TRANSLATE("Video input:"), InputMenu());
498 BMenuField* outputMenuField = new BMenuField("outputMenuField",
499 B_TRANSLATE("Video output:"), OutputMenu());
501 BLayoutBuilder::Grid<>(defaultsGridView)
502 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
503 B_USE_DEFAULT_SPACING)
504 .AddMenuField(inputMenuField, 0, 0)
505 .AddMenuField(outputMenuField, 0, 1);
507 defaultsBox->AddChild(defaultsGridView);
509 BLayoutBuilder::Group<>(this)
510 .SetInsets(0, 0, 0, 0)
511 .Add(defaultsBox)
512 .AddGroup(B_HORIZONTAL)
513 .AddGlue()
514 .Add(MakeRestartButton())
515 .End()
516 .AddGlue();
520 void
521 VideoSettingsView::SetDefaultInput(const dormant_node_info* info)
523 SettingsView::SetDefaultInput(info);
524 _MediaWindow()->UpdateInputListItem(MediaListItem::VIDEO_TYPE, info);
525 BMediaRoster::Roster()->SetVideoInput(*info);
529 void
530 VideoSettingsView::SetDefaultOutput(const dormant_node_info* info)
532 SettingsView::SetDefaultOutput(info);
533 _MediaWindow()->UpdateOutputListItem(MediaListItem::VIDEO_TYPE, info);
534 BMediaRoster::Roster()->SetVideoOutput(*info);