2 * Copyright 2003-2011, Haiku.
3 * Distributed under the terms of the MIT License.
11 #include "MediaViews.h"
13 #include <AutoDeleter.h>
20 #include <LayoutBuilder.h>
22 #include <MediaAddOn.h>
23 #include <MediaRoster.h>
24 #include <MenuField.h>
25 #include <PopUpMenu.h>
27 #include <StringView.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
),
51 fInputMenu
= new BPopUpMenu(B_TRANSLATE("<none>"));
52 fInputMenu
->SetLabelFromMarked(true);
55 fOutputMenu
= new BPopUpMenu(B_TRANSLATE("<none>"));
56 fOutputMenu
->SetLabelFromMarked(true);
61 SettingsView::MakeRestartButton()
63 return new BButton("restartButton",
64 B_TRANSLATE("Restart media services"),
65 new BMessage(ML_RESTART_MEDIA_SERVER
),
72 SettingsView::AddInputNodes(NodeList
& list
)
74 _EmptyMenu(fInputMenu
);
76 BMessage
message(MEDIA_DEFAULT_INPUT_CHANGE
);
77 _PopulateMenu(fInputMenu
, list
, message
);
82 SettingsView::AddOutputNodes(NodeList
& list
)
84 _EmptyMenu(fOutputMenu
);
86 BMessage
message(MEDIA_DEFAULT_OUTPUT_CHANGE
);
87 _PopulateMenu(fOutputMenu
, list
, message
);
92 SettingsView::SetDefaultInput(const dormant_node_info
* info
)
94 _ClearMenuSelection(fInputMenu
);
95 NodeMenuItem
* item
= _FindNodeItem(fInputMenu
, info
);
97 item
->SetMarked(true);
102 SettingsView::SetDefaultOutput(const dormant_node_info
* info
)
104 _ClearMenuSelection(fOutputMenu
);
105 NodeMenuItem
* item
= _FindNodeItem(fOutputMenu
, info
);
107 item
->SetMarked(true);
112 SettingsView::MessageReceived(BMessage
* message
)
114 switch (message
->what
) {
115 case MEDIA_DEFAULT_INPUT_CHANGE
:
118 if (message
->FindInt32("index", &index
)!=B_OK
)
121 = static_cast<NodeMenuItem
*>(fInputMenu
->ItemAt(index
));
122 SetDefaultInput(item
->NodeInfo());
125 case MEDIA_DEFAULT_OUTPUT_CHANGE
:
128 if (message
->FindInt32("index", &index
)!=B_OK
)
131 = static_cast<NodeMenuItem
*>(fOutputMenu
->ItemAt(index
));
132 SetDefaultOutput(item
->NodeInfo());
136 BGroupView::MessageReceived(message
);
142 SettingsView::AttachedToWindow()
144 BMessenger
thisMessenger(this);
145 fInputMenu
->SetTargetForItems(thisMessenger
);
146 fOutputMenu
->SetTargetForItems(thisMessenger
);
151 SettingsView::_MediaWindow() const
153 return static_cast<MediaWindow
*>(Window());
158 SettingsView::_EmptyMenu(BMenu
* menu
)
160 while (menu
->CountItems() > 0)
161 delete menu
->RemoveItem((int32
)0);
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));
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
) {
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
),
215 NodeMenuItem::Invoke(BMessage
* message
)
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
),
232 ChannelMenuItem::~ChannelMenuItem()
239 ChannelMenuItem::DestinationID()
241 return fInput
->destination
.id
;
246 ChannelMenuItem::Input()
253 ChannelMenuItem::Invoke(BMessage
* message
)
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)
285 .AddGroup(B_HORIZONTAL
)
286 .Add(_MakeVolumeCheckBox())
288 .Add(MakeRestartButton())
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
);
305 AudioSettingsView::AttachedToWindow()
307 SettingsView::AttachedToWindow();
309 BMessenger
thisMessenger(this);
310 fChannelMenu
->SetTargetForItems(thisMessenger
);
311 fVolumeCheckBox
->SetTarget(thisMessenger
);
316 AudioSettingsView::MessageReceived(BMessage
* message
)
318 switch (message
->what
) {
319 case ML_DEFAULT_CHANNEL_CHANGED
:
322 if (message
->FindInt32("index", &index
) != B_OK
)
324 ChannelMenuItem
* item
= _ChannelMenuItemAt(index
);
327 BMediaRoster
* roster
= BMediaRoster::Roster();
328 roster
->SetAudioOutput(*item
->Input());
330 fprintf(stderr
, "ChannelMenuItem not found\n");
333 case MEDIA_SHOW_HIDE_VOLUME_CONTROL
:
335 if (fVolumeCheckBox
->Value() == B_CONTROL_ON
)
336 _ShowDeskbarVolumeControl();
338 _HideDeskbarVolumeControl();
343 SettingsView::MessageReceived(message
);
349 AudioSettingsView::SetDefaultInput(const dormant_node_info
* info
)
351 SettingsView::SetDefaultInput(info
);
352 _MediaWindow()->UpdateInputListItem(MediaListItem::AUDIO_TYPE
, info
);
353 BMediaRoster::Roster()->SetAudioInput(*info
);
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
);
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
;
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
;
393 AudioSettingsView::_FillChannelMenu(const dormant_node_info
* nodeInfo
)
395 _EmptyMenu(fChannelMenu
);
397 BMediaRoster
* roster
= BMediaRoster::Roster();
399 media_node_id node_id
;
401 status_t err
= roster
->GetInstancesFor(nodeInfo
->addon
,
402 nodeInfo
->flavor_id
, &node_id
);
404 err
= roster
->InstantiateDormantNode(*nodeInfo
, &node
,
407 err
= roster
->GetNodeFor(node_id
, &node
);
411 int32 inputCount
= 4;
412 media_input
* inputs
= new media_input
[inputCount
];
413 BPrivate::ArrayDeleter
<media_input
> inputDeleter(inputs
);
416 int32 realInputCount
= 0;
417 err
= roster
->GetAllInputsFor(node
, inputs
,
418 inputCount
, &realInputCount
);
419 if (realInputCount
> inputCount
) {
421 inputs
= new media_input
[inputCount
];
422 inputDeleter
.SetTo(inputs
);
424 inputCount
= realInputCount
;
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);
446 fChannelMenu
->SetTargetForItems(BMessenger(this));
451 AudioSettingsView::_ShowDeskbarVolumeControl()
454 BEntry
entry("/bin/desklink", true);
457 status_t status
= entry
.GetRef(&ref
);
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"),
470 AudioSettingsView::_HideDeskbarVolumeControl()
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"),
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)
512 .AddGroup(B_HORIZONTAL
)
514 .Add(MakeRestartButton())
521 VideoSettingsView::SetDefaultInput(const dormant_node_info
* info
)
523 SettingsView::SetDefaultInput(info
);
524 _MediaWindow()->UpdateInputListItem(MediaListItem::VIDEO_TYPE
, info
);
525 BMediaRoster::Roster()->SetVideoInput(*info
);
530 VideoSettingsView::SetDefaultOutput(const dormant_node_info
* info
)
532 SettingsView::SetDefaultOutput(info
);
533 _MediaWindow()->UpdateOutputListItem(MediaListItem::VIDEO_TYPE
, info
);
534 BMediaRoster::Roster()->SetVideoOutput(*info
);