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())
287 .Add(MakeRestartButton())
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
);
304 AudioSettingsView::AttachedToWindow()
306 SettingsView::AttachedToWindow();
308 BMessenger
thisMessenger(this);
309 fChannelMenu
->SetTargetForItems(thisMessenger
);
310 fVolumeCheckBox
->SetTarget(thisMessenger
);
315 AudioSettingsView::MessageReceived(BMessage
* message
)
317 switch (message
->what
) {
318 case ML_DEFAULT_CHANNEL_CHANGED
:
321 if (message
->FindInt32("index", &index
) != B_OK
)
323 ChannelMenuItem
* item
= _ChannelMenuItemAt(index
);
326 BMediaRoster
* roster
= BMediaRoster::Roster();
327 roster
->SetAudioOutput(*item
->Input());
329 fprintf(stderr
, "ChannelMenuItem not found\n");
332 case MEDIA_SHOW_HIDE_VOLUME_CONTROL
:
334 if (fVolumeCheckBox
->Value() == B_CONTROL_ON
)
335 _ShowDeskbarVolumeControl();
337 _HideDeskbarVolumeControl();
342 SettingsView::MessageReceived(message
);
348 AudioSettingsView::SetDefaultInput(const dormant_node_info
* info
)
350 SettingsView::SetDefaultInput(info
);
351 _MediaWindow()->UpdateInputListItem(MediaListItem::AUDIO_TYPE
, info
);
352 BMediaRoster::Roster()->SetAudioInput(*info
);
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
);
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
;
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
;
392 AudioSettingsView::_FillChannelMenu(const dormant_node_info
* nodeInfo
)
394 _EmptyMenu(fChannelMenu
);
396 BMediaRoster
* roster
= BMediaRoster::Roster();
398 media_node_id node_id
;
400 status_t err
= roster
->GetInstancesFor(nodeInfo
->addon
,
401 nodeInfo
->flavor_id
, &node_id
);
403 err
= roster
->InstantiateDormantNode(*nodeInfo
, &node
,
406 err
= roster
->GetNodeFor(node_id
, &node
);
410 int32 inputCount
= 4;
411 media_input
* inputs
= new media_input
[inputCount
];
412 BPrivate::ArrayDeleter
<media_input
> inputDeleter(inputs
);
415 int32 realInputCount
= 0;
416 err
= roster
->GetAllInputsFor(node
, inputs
,
417 inputCount
, &realInputCount
);
418 if (realInputCount
> inputCount
) {
420 inputs
= new media_input
[inputCount
];
421 inputDeleter
.SetTo(inputs
);
423 inputCount
= realInputCount
;
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);
445 fChannelMenu
->SetTargetForItems(BMessenger(this));
450 AudioSettingsView::_ShowDeskbarVolumeControl()
453 BEntry
entry("/bin/desklink", true);
456 status_t status
= entry
.GetRef(&ref
);
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"),
469 AudioSettingsView::_HideDeskbarVolumeControl()
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"),
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)
511 .AddGroup(B_HORIZONTAL
)
513 .Add(MakeRestartButton())
520 VideoSettingsView::SetDefaultInput(const dormant_node_info
* info
)
522 SettingsView::SetDefaultInput(info
);
523 _MediaWindow()->UpdateInputListItem(MediaListItem::VIDEO_TYPE
, info
);
524 BMediaRoster::Roster()->SetVideoInput(*info
);
529 VideoSettingsView::SetDefaultOutput(const dormant_node_info
* info
)
531 SettingsView::SetDefaultOutput(info
);
532 _MediaWindow()->UpdateOutputListItem(MediaListItem::VIDEO_TYPE
, info
);
533 BMediaRoster::Roster()->SetVideoOutput(*info
);