In Media preflet:

* Modify MediaListItem to use the visitor pattern
* Use the visitor pattern for comparison of MediaListItem subclassed objects
* Use the visitor pattern in MediaWindow to propagate changes to NodeListItems.
* Rename and/or remove some message constants
* Rename SettingsItem class to NodeMenuItem 
* Rename Settings2Item class to ChannelMenuItem
* Derive SettingsView from BGridView, and make it an abstract base class for two new classes, AudioSettingsView and VideoSettingsView.
* Have the SettingsView subclasses handle messages originating from their children (for the most part).
* Use a BCardLayout to hold our Audio/Video SettingsViews and our instantiated node view (when applicable).
* small changes


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40127 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alex Wilson
2011-01-05 20:47:17 +00:00
parent 197f59b07d
commit 7afc775630
7 changed files with 928 additions and 534 deletions
+1 -1
View File
@@ -57,8 +57,8 @@ Media::Media()
}
}
fWindow = new MediaWindow(rect);
MediaListItem::SetIcons(&fIcons);
fWindow = new MediaWindow(rect);
be_roster->StartWatching(BMessenger(this));
}
+102 -57
View File
@@ -174,11 +174,10 @@ MediaListItem::Compare(const void* itemOne, const void* itemTwo)
// #pragma mark - NodeListItem
NodeListItem::NodeListItem(dormant_node_info* node, media_type type)
NodeListItem::NodeListItem(const dormant_node_info* node, media_type type)
:
MediaListItem(),
fNodeInfo(node),
fIsAudioMixer(false),
fMediaType(type),
fIsDefaultInput(false),
fIsDefaultOutput(false)
@@ -189,19 +188,14 @@ NodeListItem::NodeListItem(dormant_node_info* node, media_type type)
void
NodeListItem::SetRenderParameters(MediaListItem::Renderer& renderer)
{
MediaIcons::IconSet* iconSet = &Icons()->videoIcons;
if (fMediaType == MediaListItem::AUDIO_TYPE)
iconSet = &Icons()->audioIcons;
if (fIsAudioMixer) {
renderer.AddIcon(&Icons()->mixerIcon);
} else {
MediaIcons::IconSet* iconSet = &Icons()->videoIcons;
if (fMediaType == MediaListItem::AUDIO_TYPE)
iconSet = &Icons()->audioIcons;
if (fIsDefaultInput)
renderer.AddIcon(&iconSet->inputIcon);
if (fIsDefaultOutput)
renderer.AddIcon(&iconSet->outputIcon);
}
if (fIsDefaultInput)
renderer.AddIcon(&iconSet->inputIcon);
if (fIsDefaultOutput)
renderer.AddIcon(&iconSet->outputIcon);
}
@@ -240,40 +234,55 @@ NodeListItem::AlterWindow(MediaWindow* window)
}
void
NodeListItem::Accept(MediaListItem::Visitor& visitor)
{
visitor.Visit(this);
}
int
NodeListItem::CompareWith(MediaListItem* item)
{
return item->CompareWith(this) * -1;
Comparator comparator(this);
item->Accept(comparator);
return comparator.result;
}
int
NodeListItem::CompareWith(NodeListItem* item)
NodeListItem::Comparator::Comparator(NodeListItem* compareOthersTo)
:
result(GREATER_THAN),
fTarget(compareOthersTo)
{
if (fMediaType != item->fMediaType)
return fMediaType == AUDIO_TYPE ? GREATER_THAN : LESS_THAN;
if (fIsAudioMixer != item->fIsAudioMixer)
return fIsAudioMixer ? GREATER_THAN : LESS_THAN;
return strcmp(Label(), item->Label());
}
int
NodeListItem::CompareWith(DeviceListItem* deviceItem)
void
NodeListItem::Comparator::Visit(NodeListItem* item)
{
if (fMediaType != deviceItem->Type())
return fMediaType == AUDIO_TYPE ? GREATER_THAN : LESS_THAN;
result = GREATER_THAN;
if (fTarget->Type() != item->Type() && fTarget->Type() == VIDEO_TYPE)
result = LESS_THAN;
else
return LESS_THAN;
result = strcmp(fTarget->Label(), item->Label());
}
int
NodeListItem::CompareWith(AudioMixerListItem* item)
void
NodeListItem::Comparator::Visit(DeviceListItem* item)
{
return LESS_THAN;
result = LESS_THAN;
if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE)
result = GREATER_THAN;
}
void
NodeListItem::Comparator::Visit(AudioMixerListItem* item)
{
result = LESS_THAN;
}
@@ -290,35 +299,54 @@ DeviceListItem::DeviceListItem(const char* title,
}
void
DeviceListItem::Accept(MediaListItem::Visitor& visitor)
{
visitor.Visit(this);
}
int
DeviceListItem::CompareWith(MediaListItem* item)
{
return item->CompareWith(this) * -1;
Comparator comparator(this);
item->Accept(comparator);
return comparator.result;
}
int
DeviceListItem::CompareWith(NodeListItem* item)
DeviceListItem::Comparator::Comparator(DeviceListItem* compareOthersTo)
:
result(GREATER_THAN),
fTarget(compareOthersTo)
{
// let NodeListItem do the work
return item->CompareWith(this) * -1;
}
int
DeviceListItem::CompareWith(DeviceListItem* item)
void
DeviceListItem::Comparator::Visit(NodeListItem* item)
{
if (fMediaType == MediaListItem::AUDIO_TYPE)
return GREATER_THAN;
return LESS_THAN;
result = GREATER_THAN;
if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE)
result = LESS_THAN;
}
int
DeviceListItem::CompareWith(AudioMixerListItem* item)
void
DeviceListItem::Comparator::Visit(DeviceListItem* item)
{
// let AudioMixerListItem do the work too!
return item->CompareWith(this) * -1;
result = LESS_THAN;
if (fTarget->Type() == AUDIO_TYPE)
result = GREATER_THAN;
}
void
DeviceListItem::Comparator::Visit(AudioMixerListItem* item)
{
result = LESS_THAN;
if (fTarget->Type() == AUDIO_TYPE)
result = GREATER_THAN;
}
@@ -358,33 +386,50 @@ AudioMixerListItem::AlterWindow(MediaWindow* window)
}
void
AudioMixerListItem::Accept(MediaListItem::Visitor& visitor)
{
visitor.Visit(this);
}
int
AudioMixerListItem::CompareWith(MediaListItem* item)
{
return item->CompareWith(this) * -1;
Comparator comparator(this);
item->Accept(comparator);
return comparator.result;
}
int
AudioMixerListItem::CompareWith(NodeListItem* item)
AudioMixerListItem::Comparator::Comparator(AudioMixerListItem* compareOthersTo)
:
result(0),
fTarget(compareOthersTo)
{
return GREATER_THAN;
}
int
AudioMixerListItem::CompareWith(DeviceListItem* item)
void
AudioMixerListItem::Comparator::Visit(NodeListItem* item)
{
result = GREATER_THAN;
}
void
AudioMixerListItem::Comparator::Visit(DeviceListItem* item)
{
result = GREATER_THAN;
if (item->Type() == AUDIO_TYPE)
return LESS_THAN;
return GREATER_THAN;
result = LESS_THAN;
}
int
AudioMixerListItem::CompareWith(AudioMixerListItem* item)
void
AudioMixerListItem::Comparator::Visit(AudioMixerListItem* item)
{
return 0;
result = 0;
}
+54 -35
View File
@@ -44,9 +44,6 @@ public:
virtual void Update(BView* owner, const BFont* font);
virtual void DrawItem(BView* owner, BRect frame,
bool complete = false);
// TODO: refactor and remove this:
virtual dormant_node_info* NodeInfo() = 0;
virtual const char* Label() = 0;
@@ -54,16 +51,20 @@ public:
static MediaIcons* Icons() {return sIcons;}
static void SetIcons(MediaIcons* icons) {sIcons = icons;}
static int Compare(const void* itemOne,
const void* itemTwo);
struct Visitor {
virtual void Visit(AudioMixerListItem* item) = 0;
virtual void Visit(DeviceListItem* item) = 0;
virtual void Visit(NodeListItem* item) = 0;
};
// use double dispatch for comparison,
// returning item->CompareWith(this) * -1
virtual void Accept(Visitor& visitor) = 0;
// use the visitor pattern for comparison,
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(MediaListItem* item) = 0;
virtual int CompareWith(NodeListItem* item) = 0;
virtual int CompareWith(DeviceListItem* item) = 0;
virtual int CompareWith(AudioMixerListItem* item) = 0;
static int Compare(const void* itemOne,
const void* itemTwo);
protected:
struct Renderer;
@@ -78,7 +79,7 @@ private:
class NodeListItem : public MediaListItem {
public:
NodeListItem(dormant_node_info* node,
NodeListItem(const dormant_node_info* node,
media_type type);
void SetMediaType(MediaListItem::media_type type);
@@ -89,25 +90,32 @@ public:
virtual void AlterWindow(MediaWindow* window);
// TODO: refactor and remove this:
virtual dormant_node_info* NodeInfo(){return fNodeInfo;}
virtual const char* Label();
media_type Type() {return fMediaType;}
virtual int CompareWith(MediaListItem* item);
virtual void Accept(MediaListItem::Visitor& visitor);
struct Comparator : public MediaListItem::Visitor {
Comparator(NodeListItem* compareOthersTo);
virtual void Visit(NodeListItem* item);
virtual void Visit(DeviceListItem* item);
virtual void Visit(AudioMixerListItem* item);
int result;
// -1 : < item; 0 : == item; 1 : > item
private:
NodeListItem* fTarget;
};
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(NodeListItem* item);
virtual int CompareWith(DeviceListItem* item);
virtual int CompareWith(AudioMixerListItem* item);
virtual int CompareWith(MediaListItem* item);
private:
virtual void SetRenderParameters(Renderer& renderer);
dormant_node_info* fNodeInfo;
bool fIsAudioMixer;
const dormant_node_info* fNodeInfo;
media_type fMediaType;
bool fIsDefaultInput;
bool fIsDefaultOutput;
@@ -120,19 +128,24 @@ public:
MediaListItem::media_type type);
MediaListItem::media_type Type() {return fMediaType;}
// TODO: refactor and remove this:
virtual dormant_node_info* NodeInfo(){return NULL;}
virtual const char* Label() {return fTitle;}
virtual void AlterWindow(MediaWindow* window);
virtual void Accept(MediaListItem::Visitor& visitor);
virtual int CompareWith(MediaListItem* item);
struct Comparator : public MediaListItem::Visitor {
Comparator(DeviceListItem* compareOthersTo);
virtual void Visit(NodeListItem* item);
virtual void Visit(DeviceListItem* item);
virtual void Visit(AudioMixerListItem* item);
int result;
// -1 : < item; 0 : == item; 1 : > item
private:
DeviceListItem* fTarget;
};
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(NodeListItem* item);
virtual int CompareWith(DeviceListItem* item);
virtual int CompareWith(AudioMixerListItem* item);
virtual int CompareWith(MediaListItem* item);
private:
virtual void SetRenderParameters(Renderer& renderer);
@@ -146,19 +159,25 @@ class AudioMixerListItem : public MediaListItem {
public:
AudioMixerListItem(const char* title);
// TODO: refactor and remove this:
virtual dormant_node_info* NodeInfo(){return NULL;}
virtual const char* Label() {return fTitle;}
virtual void AlterWindow(MediaWindow* window);
virtual void Accept(MediaListItem::Visitor& visitor);
virtual int CompareWith(MediaListItem* item);
struct Comparator : public MediaListItem::Visitor {
Comparator(AudioMixerListItem* compareOthersTo);
virtual void Visit(NodeListItem* item);
virtual void Visit(DeviceListItem* item);
virtual void Visit(AudioMixerListItem* item);
int result;
// -1 : < item; 0 : == item; 1 : > item
private:
AudioMixerListItem* fTarget;
};
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(NodeListItem* item);
virtual int CompareWith(DeviceListItem* item);
virtual int CompareWith(AudioMixerListItem* item);
virtual int CompareWith(MediaListItem* item);
private:
virtual void SetRenderParameters(Renderer& renderer);
+514 -172
View File
@@ -12,248 +12,287 @@
// Created : June 25, 2003
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#include "MediaViews.h"
#include <AutoDeleter.h>
#include <Box.h>
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <Deskbar.h>
#include <Entry.h>
#include <GridView.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <Locale.h>
#include <MediaAddOn.h>
#include <MediaRoster.h>
#include <MenuField.h>
#include <PopUpMenu.h>
#include <SpaceLayoutItem.h>
#include <String.h>
#include <StringView.h>
#include <TextView.h>
#include <assert.h>
#include <stdio.h>
#include "MediaWindow.h"
#undef B_TRANSLATE_CONTEXT
#define B_TRANSLATE_CONTEXT "Media views"
#define MEDIA_DEFAULT_INPUT_CHANGE 'dich'
#define MEDIA_DEFAULT_OUTPUT_CHANGE 'doch'
#define MEDIA_SHOW_HIDE_VOLUME_CONTROL 'shvc'
SettingsView::SettingsView (bool isVideo)
SettingsView::SettingsView()
:
BView("SettingsView", B_WILL_DRAW | B_SUPPORTS_LAYOUT),
fIsVideo(isVideo)
BGridView(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING),
fRealtimeCheckBox(NULL),
fInputMenu(NULL),
fOutputMenu(NULL),
fRestartView(NULL)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// create the default box
// input menu
fInputMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
fInputMenu->SetLabelFromMarked(true);
BMenuField* inputMenuField = new BMenuField("inputMenuField",
fIsVideo ? B_TRANSLATE("Video input:")
: B_TRANSLATE("Audio input:"), fInputMenu, NULL);
// output menu
// input menu
fOutputMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
fOutputMenu->SetLabelFromMarked(true);
BMenuField* outputMenuField = new BMenuField("outputMenuField",
fIsVideo ? B_TRANSLATE("Video output:")
: B_TRANSLATE("Audio output:"), fOutputMenu, NULL);
// channel menu (audio only)
BMenuField* channelMenuField = NULL;
if (!fIsVideo) {
fChannelMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
fChannelMenu->SetLabelFromMarked(true);
channelMenuField = new BMenuField("channelMenuField",
B_TRANSLATE("Channel:"), fChannelMenu, NULL);
channelMenuField->SetDivider(StringWidth(B_TRANSLATE("Channel:"))+5);
}
BBox* defaultsBox = new BBox("defaults");
defaultsBox->SetLabel(fIsVideo ? B_TRANSLATE("Default nodes")
: B_TRANSLATE("Defaults"));
// put our menus in a BGridView in our BBox, this way, the BBox makes sure
// we have are not blocking the label.
BGridView* defaultsGridView = new BGridView();
defaultsBox->AddChild(defaultsGridView);
BGridLayout* defaultsGrid = defaultsGridView->GridLayout();
defaultsGrid->SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
B_USE_DEFAULT_SPACING);
BLayoutItem* labelItem = inputMenuField->CreateLabelLayoutItem();
BLayoutItem* menuItem = inputMenuField->CreateMenuBarLayoutItem();
defaultsGrid->AddItem(labelItem, 0, 0, 1, 1);
defaultsGrid->AddItem(menuItem, 1, 0, 3, 1);
int32 outputMenuWidth = 3;
if (channelMenuField) {
outputMenuWidth = 1;
labelItem = channelMenuField->CreateLabelLayoutItem();
menuItem = channelMenuField->CreateMenuBarLayoutItem();
defaultsGrid->AddItem(labelItem, 2, 1, 1, 1);
defaultsGrid->AddItem(menuItem, 3, 1, 1, 1);
}
labelItem = outputMenuField->CreateLabelLayoutItem();
menuItem = outputMenuField->CreateMenuBarLayoutItem();
defaultsGrid->AddItem(labelItem, 0, 1, 1, 1);
defaultsGrid->AddItem(menuItem, 1, 1, outputMenuWidth, 1);
}
rgb_color red_color = {222, 32, 33};
fRestartView = new BStringView("restartStringView",
B_TRANSLATE("Restart the media server to apply changes."));
fRestartView->SetHighColor(red_color);
defaultsBox->AddChild(fRestartView);
fRestartView->Hide();
BBox*
SettingsView::MakeRealtimeBox(const char* info, uint32 realtimeMask,
const char* checkBoxLabel)
{
// create the realtime box
BBox* realtimeBox = new BBox("realtime");
realtimeBox->SetLabel(B_TRANSLATE("Real-time"));
BMessage* message = new BMessage(ML_ENABLE_REAL_TIME);
message->AddBool("isVideo", fIsVideo);
fRealtimeCheckBox = new BCheckBox("realtimeCheckBox",
fIsVideo ? B_TRANSLATE("Enable real-time video")
: B_TRANSLATE("Enable real-time audio"),
message);
BMessage* checkBoxMessage = new BMessage(ML_ENABLE_REAL_TIME);
checkBoxMessage->AddUInt32("flags", realtimeMask);
fRealtimeCheckBox = new BCheckBox("realtimeCheckBox", checkBoxLabel,
checkBoxMessage);
uint32 flags;
uint32 flags = 0;
BMediaRoster::Roster()->GetRealtimeFlags(&flags);
if (flags & (fIsVideo ? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO))
if (flags & realtimeMask)
fRealtimeCheckBox->SetValue(B_CONTROL_ON);
BTextView* textView = new BTextView("stringView");
textView->Insert(fIsVideo ? B_TRANSLATE(
"Enabling real-time video allows system to "
"perform video operations as fast and smoothly as possible. It "
"achieves optimum performance by using more RAM."
"\n\nOnly enable this feature if you need the lowest latency possible.")
: B_TRANSLATE(
"Enabling real-time audio allows system to record and play audio "
"as fast as possible. It achieves this performance by using more"
" CPU and RAM.\n\nOnly enable this feature if you need the lowest"
" latency possible."));
textView->Insert(info);
textView->MakeEditable(false);
textView->MakeSelectable(false);
textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BGroupLayout* realtimeBoxLayout = new BGroupLayout(B_VERTICAL, 5);
realtimeBoxLayout->SetInsets(10,10,10,10);
realtimeBox->SetLayout(realtimeBoxLayout);
BGroupView* realtimeGroup = new BGroupView(B_VERTICAL);
BLayoutBuilder::Group<>(realtimeGroup)
.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
B_USE_DEFAULT_SPACING)
.Add(fRealtimeCheckBox)
.Add(textView);
realtimeBoxLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(5));
realtimeBoxLayout->AddView(fRealtimeCheckBox);
realtimeBoxLayout->AddView(textView);
realtimeBox->AddChild(realtimeGroup);
return realtimeBox;
}
// create the bottom line: volume in deskbar checkbox and restart button
BGroupView* bottomView = new BGroupView(B_HORIZONTAL);
BButton* restartButton = new BButton("restartButton",
BStringView*
SettingsView::MakeRestartMessageView()
{
// note: this ought to display at the bottom of the default box...
fRestartView = new BStringView("restartStringView",
B_TRANSLATE("Restart the media server to apply changes."));
fRestartView->SetHighColor(ui_color(B_FAILURE_COLOR));
// not exactly failure, but sort of.
fRestartView->Hide();
fRestartView->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER,
B_ALIGN_VERTICAL_CENTER));
fRestartView->SetAlignment(B_ALIGN_HORIZONTAL_CENTER);
fRestartView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
return fRestartView;
}
BButton*
SettingsView::MakeRestartButton()
{
return new BButton("restartButton",
B_TRANSLATE("Restart media services"),
new BMessage(ML_RESTART_MEDIA_SERVER));
}
if (!fIsVideo) {
fVolumeCheckBox = new BCheckBox("volumeCheckBox",
B_TRANSLATE("Show volume control on Deskbar"),
new BMessage(ML_SHOW_VOLUME_CONTROL));
bottomView->GroupLayout()->AddView(fVolumeCheckBox);
if (BDeskbar().HasItem("MediaReplicant"))
fVolumeCheckBox->SetValue(B_CONTROL_ON);
}
else{
bottomView->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
}
bottomView->GroupLayout()->AddView(restartButton);
// compose all stuff
BGroupLayout* rootlayout = new BGroupLayout(B_VERTICAL, 5);
SetLayout(rootlayout);
rootlayout->AddView(defaultsBox);
rootlayout->AddView(realtimeBox);
rootlayout->AddView(bottomView);
void
SettingsView::AddInputNodes(NodeList& list)
{
_EmptyMenu(fInputMenu);
BMessage message(MEDIA_DEFAULT_INPUT_CHANGE);
_PopulateMenu(fInputMenu, list, message);
}
void
SettingsView::AddNodes(NodeList& list, bool isInput)
SettingsView::AddOutputNodes(NodeList& list)
{
BMenu* menu = isInput ? fInputMenu : fOutputMenu;
_EmptyMenu(fOutputMenu);
for (BMenuItem* item; (item = menu->RemoveItem((int32)0)) != NULL;)
delete item;
BMessage message(ML_DEFAULT_CHANGE);
message.AddBool("isVideo", fIsVideo);
message.AddBool("isInput", isInput);
for (int32 i = 0; i < list.CountItems(); i++) {
dormant_node_info* info = list.ItemAt(i);
menu->AddItem(new SettingsItem(info, new BMessage(message)));
}
BMessage message(MEDIA_DEFAULT_OUTPUT_CHANGE);
_PopulateMenu(fOutputMenu, list, message);
}
void
SettingsView::SetDefault(dormant_node_info &info, bool isInput, int32 outputID)
SettingsView::SetDefaultInput(const dormant_node_info* info)
{
BMenu* menu = isInput ? fInputMenu : fOutputMenu;
_ClearMenuSelection(fInputMenu);
NodeMenuItem* item = _FindNodeItem(fInputMenu, info);
if (item)
item->SetMarked(true);
}
for (int32 i = 0; i < menu->CountItems(); i++) {
SettingsItem* item = static_cast<SettingsItem*>(menu->ItemAt(i));
if (item->fInfo && item->fInfo->addon == info.addon
&& item->fInfo->flavor_id == info.flavor_id) {
item->SetMarked(true);
void
SettingsView::SetDefaultOutput(const dormant_node_info* info)
{
_ClearMenuSelection(fOutputMenu);
NodeMenuItem* item = _FindNodeItem(fOutputMenu, info);
if (item)
item->SetMarked(true);
}
void
SettingsView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MEDIA_DEFAULT_INPUT_CHANGE:
{
int32 index;
if (message->FindInt32("index", &index)!=B_OK)
break;
NodeMenuItem* item
= static_cast<NodeMenuItem*>(fInputMenu->ItemAt(index));
SetDefaultInput(item->NodeInfo());
RestartRequired(true);
}
case MEDIA_DEFAULT_OUTPUT_CHANGE:
{
int32 index;
if (message->FindInt32("index", &index)!=B_OK)
break;
NodeMenuItem* item
= static_cast<NodeMenuItem*>(fOutputMenu->ItemAt(index));
SetDefaultOutput(item->NodeInfo());
RestartRequired(true);
}
case ML_ENABLE_REAL_TIME:
{
uint32 flags = 0;
if (message->FindUInt32("flags", &flags) == B_OK)
_FlipRealtimeFlag(flags);
break;
}
}
BGridView::MessageReceived(message);
}
if (!fIsVideo && !isInput && outputID >= 0) {
BMenuItem* item;
while ((item = fChannelMenu->RemoveItem((int32)0)) != NULL)
delete item;
BMediaRoster* roster = BMediaRoster::Roster();
media_node node;
media_node_id node_id;
status_t err;
if (roster->GetInstancesFor(info.addon, info.flavor_id,
&node_id) != B_OK) {
err = roster->InstantiateDormantNode(info, &node,
B_FLAVOR_IS_GLOBAL);
} else {
err = roster->GetNodeFor(node_id, &node);
void
SettingsView::AttachedToWindow()
{
BMessenger thisMessenger(this);
fInputMenu->SetTargetForItems(thisMessenger);
fOutputMenu->SetTargetForItems(thisMessenger);
fRealtimeCheckBox->SetTarget(thisMessenger);
}
void
SettingsView::RestartRequired(bool required)
{
if (required)
fRestartView->Show();
else
fRestartView->Hide();
}
MediaWindow*
SettingsView::_MediaWindow() const
{
return static_cast<MediaWindow*>(Window());
}
void
SettingsView::_FlipRealtimeFlag(uint32 mask)
{
// TODO: error codes
uint32 flags = 0;
BMediaRoster* roster = BMediaRoster::Roster();
roster->GetRealtimeFlags(&flags);
if (flags & mask)
flags &= ~mask;
else
flags |= mask;
roster->SetRealtimeFlags(flags);
}
void
SettingsView::_EmptyMenu(BMenu* menu)
{
while (menu->CountItems() > 0)
delete menu->RemoveItem((int32)0);
}
void
SettingsView::_PopulateMenu(BMenu* menu, NodeList& nodes,
const BMessage& message)
{
for (int32 i = 0; i < nodes.CountItems(); i++) {
dormant_node_info* info = nodes.ItemAt(i);
menu->AddItem(new NodeMenuItem(info, new BMessage(message)));
}
if (Window() != NULL)
menu->SetTargetForItems(BMessenger(this));
}
NodeMenuItem*
SettingsView::_FindNodeItem(BMenu* menu, const dormant_node_info* nodeInfo)
{
for (int32 i = 0; i < menu->CountItems(); i++) {
NodeMenuItem* item = static_cast<NodeMenuItem*>(menu->ItemAt(i));
const dormant_node_info* itemInfo = item->NodeInfo();
if (itemInfo && itemInfo->addon == nodeInfo->addon
&& itemInfo->flavor_id == nodeInfo->flavor_id) {
return item;
}
}
return NULL;
}
if (err == B_OK) {
media_input inputs[16];
int32 inputCount = 16;
if (roster->GetAllInputsFor(node, inputs, 16, &inputCount)==B_OK) {
BMessage message(ML_DEFAULTOUTPUT_CHANGE);
for (int32 i = 0; i < inputCount; i++) {
media_input* input = new media_input();
memcpy(input, &inputs[i], sizeof(*input));
item = new Settings2Item(&info, input,
new BMessage(message));
fChannelMenu->AddItem(item);
if (inputs[i].destination.id == outputID)
item->SetMarked(true);
}
}
}
void
SettingsView::_ClearMenuSelection(BMenu* menu)
{
for (int32 i = 0; i < menu->CountItems(); i++) {
BMenuItem* item = menu->ItemAt(i);
item->SetMarked(false);
}
}
SettingsItem::SettingsItem(dormant_node_info* info, BMessage* message,
char shortcut, uint32 modifiers)
NodeMenuItem::NodeMenuItem(const dormant_node_info* info, BMessage* message,
char shortcut, uint32 modifiers)
:
BMenuItem(info->name, message, shortcut, modifiers),
fInfo(info)
@@ -263,7 +302,7 @@ SettingsItem::SettingsItem(dormant_node_info* info, BMessage* message,
status_t
SettingsItem::Invoke(BMessage* message)
NodeMenuItem::Invoke(BMessage* message)
{
if (IsMarked())
return B_OK;
@@ -271,27 +310,330 @@ SettingsItem::Invoke(BMessage* message)
}
Settings2Item::Settings2Item(dormant_node_info* info, media_input* input,
BMessage* message, char shortcut, uint32 modifiers)
ChannelMenuItem::ChannelMenuItem(media_input* input, BMessage* message,
char shortcut, uint32 modifiers)
:
BMenuItem(input->name, message, shortcut, modifiers),
fInfo(info),
fInput(input)
{
}
Settings2Item::~Settings2Item()
ChannelMenuItem::~ChannelMenuItem()
{
delete fInput;
}
int32
ChannelMenuItem::DestinationID()
{
return fInput->destination.id;
}
media_input*
ChannelMenuItem::Input()
{
return fInput;
}
status_t
Settings2Item::Invoke(BMessage* message)
ChannelMenuItem::Invoke(BMessage* message)
{
if (IsMarked())
return B_OK;
return BMenuItem::Invoke(message);
}
AudioSettingsView::AudioSettingsView()
{
BBox* defaultsBox = new BBox("defaults");
defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
BGridView* defaultsGridView = new BGridView();
BMenuField* inputMenuField = new BMenuField("inputMenuField",
B_TRANSLATE("Audio input:"), InputMenu(), NULL);
BMenuField* outputMenuField = new BMenuField("outputMenuField",
B_TRANSLATE("Audio output:"), OutputMenu(), NULL);
BLayoutBuilder::Grid<>(defaultsGridView)
.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0)
.AddMenuField(inputMenuField, 0, 0, B_ALIGN_HORIZONTAL_UNSET, 1, 3, 1)
.AddMenuField(outputMenuField, 0, 1)
.AddMenuField(_MakeChannelMenu(), 2, 1)
.Add(MakeRestartMessageView(), 0, 2, 4, 1);
defaultsBox->AddChild(defaultsGridView);
const char* realtimeLabel = B_TRANSLATE("Enable real-time audio");
const char* realtimeInfo = B_TRANSLATE(
"Enabling real-time audio allows system to record and play audio "
"as fast as possible. It achieves this performance by using more"
" CPU and RAM.\n\nOnly enable this feature if you need the lowest"
" latency possible.");
BLayoutBuilder::Grid<>(this)
.SetInsets(0, 0, 0, 0)
.Add(defaultsBox, 0, 0, 2, 1)
.Add(MakeRealtimeBox(realtimeInfo, B_MEDIA_REALTIME_AUDIO,
realtimeLabel), 0, 1, 2, 1)
.Add(_MakeVolumeCheckBox(),0, 2, 1, 1)
.Add(MakeRestartButton(), 1, 2, 1, 1)
.SetRowWeight(1, 10);
}
void
AudioSettingsView::SetDefaultChannel(int32 channelID)
{
for (int32 i = 0; i < fChannelMenu->CountItems(); i++) {
ChannelMenuItem* item = _ChannelMenuItemAt(i);
item->SetMarked(item->DestinationID() == channelID);
}
}
void
AudioSettingsView::AttachedToWindow()
{
SettingsView::AttachedToWindow();
BMessenger thisMessenger(this);
fChannelMenu->SetTargetForItems(thisMessenger);
fVolumeCheckBox->SetTarget(thisMessenger);
}
void
AudioSettingsView::MessageReceived(BMessage* message)
{
switch (message->what) {
case ML_DEFAULT_CHANNEL_CHANGED:
{
int32 index;
if (message->FindInt32("index", &index) != B_OK)
break;
ChannelMenuItem* item = _ChannelMenuItemAt(index);
if (item) {
BMediaRoster* roster = BMediaRoster::Roster();
roster->SetAudioOutput(*item->Input());
RestartRequired(true);
} else
fprintf(stderr, "ChannelMenuItem not found\n");
}
break;
case MEDIA_SHOW_HIDE_VOLUME_CONTROL:
{
if (fVolumeCheckBox->Value() == B_CONTROL_ON)
_ShowDeskbarVolumeControl();
else
_HideDeskbarVolumeControl();
break;
}
default:
SettingsView::MessageReceived(message);
}
}
void
AudioSettingsView::SetDefaultInput(const dormant_node_info* info)
{
SettingsView::SetDefaultInput(info);
_MediaWindow()->UpdateInputListItem(MediaListItem::AUDIO_TYPE, info);
BMediaRoster::Roster()->SetAudioInput(*info);
}
void
AudioSettingsView::SetDefaultOutput(const dormant_node_info* info)
{
SettingsView::SetDefaultOutput(info);
_MediaWindow()->UpdateOutputListItem(MediaListItem::AUDIO_TYPE, info);
_FillChannelMenu(info);
BMediaRoster::Roster()->SetAudioOutput(*info);
}
BMenuField*
AudioSettingsView::_MakeChannelMenu()
{
fChannelMenu = new BPopUpMenu(B_TRANSLATE("<none>"));
fChannelMenu->SetLabelFromMarked(true);
BMenuField* channelMenuField = new BMenuField("channelMenuField",
B_TRANSLATE("Channel:"), fChannelMenu, NULL);
return channelMenuField;
}
BCheckBox*
AudioSettingsView::_MakeVolumeCheckBox()
{
fVolumeCheckBox = new BCheckBox("volumeCheckBox",
B_TRANSLATE("Show volume control on Deskbar"),
new BMessage(MEDIA_SHOW_HIDE_VOLUME_CONTROL));
if (BDeskbar().HasItem("MediaReplicant"))
fVolumeCheckBox->SetValue(B_CONTROL_ON);
return fVolumeCheckBox;
}
void
AudioSettingsView::_FillChannelMenu(const dormant_node_info* nodeInfo)
{
_EmptyMenu(fChannelMenu);
BMediaRoster* roster = BMediaRoster::Roster();
media_node node;
media_node_id node_id;
status_t err = roster->GetInstancesFor(nodeInfo->addon,
nodeInfo->flavor_id, &node_id);
if (err != B_OK) {
err = roster->InstantiateDormantNode(*nodeInfo, &node,
B_FLAVOR_IS_GLOBAL);
} else {
err = roster->GetNodeFor(node_id, &node);
}
if (err == B_OK) {
int32 inputCount = 4;
media_input* inputs = new media_input[inputCount];
BPrivate::ArrayDeleter<media_input> inputDeleter(inputs);
while (true) {
int32 realInputCount = 0;
err = roster->GetAllInputsFor(node, inputs,
inputCount, &realInputCount);
if (realInputCount > inputCount) {
inputCount *= 2;
inputs = new media_input[inputCount];
inputDeleter.SetTo(inputs);
} else {
inputCount = realInputCount;
break;
}
}
if (err == B_OK) {
BMessage message(ML_DEFAULT_CHANNEL_CHANGED);
for (int32 i = 0; i < inputCount; i++) {
media_input* input = new media_input();
memcpy(input, &inputs[i], sizeof(*input));
ChannelMenuItem* channelItem = new ChannelMenuItem(input,
new BMessage(message));
fChannelMenu->AddItem(channelItem);
if (channelItem->DestinationID() == 0)
channelItem->SetMarked(true);
}
}
}
if (Window())
fChannelMenu->SetTargetForItems(BMessenger(this));
}
void
AudioSettingsView::_ShowDeskbarVolumeControl()
{
BDeskbar deskbar;
BEntry entry("/bin/desklink", true);
int32 id;
entry_ref ref;
status_t status = entry.GetRef(&ref);
if (status == B_OK)
status = deskbar.AddItem(&ref, &id);
if (status != B_OK) {
fprintf(stderr, B_TRANSLATE(
"Couldn't add volume control in Deskbar: %s\n"),
strerror(status));
}
}
void
AudioSettingsView::_HideDeskbarVolumeControl()
{
BDeskbar deskbar;
status_t status = deskbar.RemoveItem("MediaReplicant");
if (status != B_OK) {
fprintf(stderr, B_TRANSLATE(
"Couldn't remove volume control in Deskbar: %s\n"),
strerror(status));
}
}
ChannelMenuItem*
AudioSettingsView::_ChannelMenuItemAt(int32 index)
{
return static_cast<ChannelMenuItem*>(fChannelMenu->ItemAt(index));
}
VideoSettingsView::VideoSettingsView()
{
BBox* defaultsBox = new BBox("defaults");
defaultsBox->SetLabel(B_TRANSLATE("Defaults"));
BGridView* defaultsGridView = new BGridView();
BMenuField* inputMenuField = new BMenuField("inputMenuField",
B_TRANSLATE("Video input:"), InputMenu(), NULL);
BMenuField* outputMenuField = new BMenuField("outputMenuField",
B_TRANSLATE("Video output:"), OutputMenu(), NULL);
BLayoutBuilder::Grid<>(defaultsGridView)
.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 0)
.AddMenuField(inputMenuField, 0, 0)
.AddMenuField(outputMenuField, 0, 1)
.Add(MakeRestartMessageView(), 0, 2, 2, 1);
defaultsBox->AddChild(defaultsGridView);
const char* realtimeLabel = B_TRANSLATE("Enable real-time video");
const char* realtimeInfo = B_TRANSLATE(
"Enabling real-time video allows system to "
"perform video operations as fast and smoothly as possible. It "
"achieves optimum performance by using more RAM.\n\n"
"Only enable this feature if you need the lowest latency possible.");
BLayoutBuilder::Grid<>(this)
.SetInsets(0, 0, 0, 0)
.Add(defaultsBox, 0, 0, 2, 1)
.Add(MakeRealtimeBox(realtimeInfo, B_MEDIA_REALTIME_VIDEO,
realtimeLabel), 0, 1, 2, 1)
.Add(MakeRestartButton(), 1, 2, 1, 1)
.SetRowWeight(1, 10);
}
void
VideoSettingsView::SetDefaultInput(const dormant_node_info* info)
{
SettingsView::SetDefaultInput(info);
_MediaWindow()->UpdateInputListItem(MediaListItem::VIDEO_TYPE, info);
BMediaRoster::Roster()->SetVideoInput(*info);
}
void
VideoSettingsView::SetDefaultOutput(const dormant_node_info* info)
{
SettingsView::SetDefaultOutput(info);
_MediaWindow()->UpdateOutputListItem(MediaListItem::VIDEO_TYPE, info);
BMediaRoster::Roster()->SetVideoOutput(*info);
}
+102 -26
View File
@@ -14,69 +14,145 @@
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#ifndef __MEDIAVIEWS_H__
#define __MEDIAVIEWS_H__
#include <CheckBox.h>
#include <GridView.h>
#include <MediaAddOn.h>
#include <MenuItem.h>
#include <StringView.h>
#include <View.h>
#include <ObjectList.h>
class BBox;
class BButton;
class BCheckBox;
class BMenu;
class BMenuField;
class BStringView;
class MediaWindow;
const uint32 ML_RESTART_MEDIA_SERVER = 'resr';
const uint32 ML_SHOW_VOLUME_CONTROL = 'shvc';
const uint32 ML_ENABLE_REAL_TIME = 'enrt';
const uint32 ML_DEFAULT_CHANGE = 'dech';
const uint32 ML_DEFAULTOUTPUT_CHANGE = 'doch';
const uint32 ML_DEFAULT_CHANNEL_CHANGED = 'chch';
class SettingsItem : public BMenuItem
class NodeMenuItem : public BMenuItem
{
public:
SettingsItem(dormant_node_info* info,
NodeMenuItem(const dormant_node_info* info,
BMessage* message, char shortcut = 0,
uint32 modifiers = 0);
virtual status_t Invoke(BMessage* message = NULL);
dormant_node_info* fInfo;
const dormant_node_info* NodeInfo() const {return fInfo;}
private:
const dormant_node_info* fInfo;
};
class Settings2Item : public BMenuItem
class ChannelMenuItem : public BMenuItem
{
public:
Settings2Item(dormant_node_info* info,
media_input* input, BMessage* message,
char shortcut = 0, uint32 modifiers = 0);
virtual ~Settings2Item();
ChannelMenuItem(media_input* input,
BMessage* message, char shortcut = 0,
uint32 modifiers = 0);
virtual ~ChannelMenuItem();
int32 DestinationID();
media_input* Input();
virtual status_t Invoke(BMessage* message = NULL);
dormant_node_info* fInfo;
private:
media_input* fInput;
};
class SettingsView : public BView
class SettingsView : public BGridView
{
public:
typedef BObjectList<dormant_node_info> NodeList;
SettingsView(bool isVideo);
void AddNodes(NodeList &nodes, bool isInput);
void SetDefault(dormant_node_info &info,
bool isInput, int32 outputID = -1);
SettingsView();
void AddInputNodes(NodeList& nodes);
void AddOutputNodes(NodeList& nodes);
virtual void SetDefaultInput(const dormant_node_info* info);
virtual void SetDefaultOutput(const dormant_node_info* info);
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
void RestartRequired(bool required);
protected:
BMenu* InputMenu() {return fInputMenu;}
BMenu* OutputMenu() {return fOutputMenu;}
BBox* MakeRealtimeBox(const char* info,
uint32 realtimeMask,
const char* checkboxLabel);
BStringView* MakeRestartMessageView();
BButton* MakeRestartButton();
void _EmptyMenu(BMenu* menu);
MediaWindow* _MediaWindow() const;
private:
void _FlipRealtimeFlag(uint32 mask);
void _PopulateMenu(BMenu* menu, NodeList& nodes,
const BMessage& message);
NodeMenuItem* _FindNodeItem(BMenu* menu,
const dormant_node_info* nodeInfo);
void _ClearMenuSelection(BMenu* menu);
BCheckBox* fRealtimeCheckBox;
BCheckBox* fVolumeCheckBox;
BMenu* fInputMenu;
BMenu* fOutputMenu;
BMenu* fChannelMenu;
// (audio only)
BStringView* fRestartView;
private:
bool fIsVideo;
};
class AudioSettingsView : public SettingsView
{
public:
AudioSettingsView();
void SetDefaultChannel(int32 channelID);
virtual void SetDefaultInput(const dormant_node_info* info);
virtual void SetDefaultOutput(const dormant_node_info* info);
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
private:
BMenuField* _MakeChannelMenu();
BCheckBox* _MakeVolumeCheckBox();
void _FillChannelMenu(const dormant_node_info* info);
void _ShowDeskbarVolumeControl();
void _HideDeskbarVolumeControl();
ChannelMenuItem* _ChannelMenuItemAt(int32 index);
BMenu* fChannelMenu;
BCheckBox* fVolumeCheckBox;
};
class VideoSettingsView : public SettingsView
{
public:
VideoSettingsView();
virtual void SetDefaultInput(const dormant_node_info* info);
virtual void SetDefaultOutput(const dormant_node_info* info);
};
#endif
+141 -234
View File
@@ -1,9 +1,10 @@
/*
* Copyright (c) 2003-2005, Haiku, Inc.
* Copyright (c) 2003-2010, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Sikosis, Jérôme Duval
* yourpalal, Alex Wilson
*/
@@ -16,10 +17,11 @@
#include <Autolock.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <Catalog.h>
#include <Debug.h>
#include <Deskbar.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <Locale.h>
#include <MediaRoster.h>
#include <MediaTheme.h>
@@ -44,6 +46,34 @@ const uint32 ML_SELECTED_NODE = 'MlSN';
const uint32 ML_INIT_MEDIA = 'MlIM';
class NodeListItemUpdater : public MediaListItem::Visitor {
public:
typedef void (NodeListItem::*UpdateMethod)(bool);
NodeListItemUpdater(NodeListItem* target, UpdateMethod action)
:
fComparator(target),
fAction(action)
{
}
virtual void Visit(AudioMixerListItem*){}
virtual void Visit(DeviceListItem*){}
virtual void Visit(NodeListItem* item)
{
item->Accept(fComparator);
(item->*(fAction))(fComparator.result == 0);
}
private:
NodeListItem::Comparator fComparator;
UpdateMethod fAction;
};
MediaWindow::SmartNode::SmartNode(const BMessenger& notifyHandler)
:
fNode(NULL),
@@ -59,17 +89,16 @@ MediaWindow::SmartNode::~SmartNode()
void
MediaWindow::SmartNode::SetTo(dormant_node_info* info)
MediaWindow::SmartNode::SetTo(const dormant_node_info* info)
{
_FreeNode();
if (!info)
return;
fNode = new media_node();
// TODO: check error codes
BMediaRoster* roster = BMediaRoster::Roster();
// TODO: error codes
media_node_id node_id;
if (roster->GetInstancesFor(info->addon, info->flavor_id, &node_id) == B_OK)
roster->GetNodeFor(node_id, fNode);
@@ -122,7 +151,7 @@ MediaWindow::SmartNode::_FreeNode()
// MediaWindow - Constructor
MediaWindow::MediaWindow(BRect frame)
:
BWindow (frame, B_TRANSLATE("Media"), B_TITLED_WINDOW,
BWindow(frame, B_TRANSLATE("Media"), B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
fCurrentNode(BMessenger(this)),
fParamWeb(NULL),
@@ -148,8 +177,6 @@ MediaWindow::~MediaWindow()
{
_EmptyNodeLists();
_ClearParamView();
delete fVideoView;
delete fAudioView;
char buffer[512];
BRect rect = Frame();
@@ -169,7 +196,7 @@ MediaWindow::~MediaWindow()
void
MediaWindow::SelectNode(dormant_node_info* node)
MediaWindow::SelectNode(const dormant_node_info* node)
{
fCurrentNode.SetTo(node);
_MakeParamView();
@@ -180,7 +207,7 @@ MediaWindow::SelectNode(dormant_node_info* node)
void
MediaWindow::SelectAudioSettings(const char* title)
{
fContentView->AddChild(fAudioView);
fContentLayout->SetVisibleItem(fContentLayout->IndexOfView(fAudioView));
fTitleView->SetLabel(title);
}
@@ -188,7 +215,7 @@ MediaWindow::SelectAudioSettings(const char* title)
void
MediaWindow::SelectVideoSettings(const char* title)
{
fContentView->AddChild(fVideoView);
fContentLayout->SetVisibleItem(fContentLayout->IndexOfView(fVideoView));
fTitleView->SetLabel(title);
}
@@ -205,6 +232,34 @@ MediaWindow::SelectAudioMixer(const char* title)
}
void
MediaWindow::UpdateInputListItem(MediaListItem::media_type type,
const dormant_node_info* node)
{
NodeListItem compareTo(node, type);
NodeListItemUpdater updater(&compareTo, &NodeListItem::SetDefaultInput);
for (int32 i = 0; i < fListView->CountItems(); i++) {
MediaListItem* item = static_cast<MediaListItem*>(fListView->ItemAt(i));
item->Accept(updater);
}
fListView->Invalidate();
}
void
MediaWindow::UpdateOutputListItem(MediaListItem::media_type type,
const dormant_node_info* node)
{
NodeListItem compareTo(node, type);
NodeListItemUpdater updater(&compareTo, &NodeListItem::SetDefaultOutput);
for (int32 i = 0; i < fListView->CountItems(); i++) {
MediaListItem* item = static_cast<MediaListItem*>(fListView->ItemAt(i));
item->Accept(updater);
}
fListView->Invalidate();
}
void
MediaWindow::_FindNodes()
{
@@ -249,7 +304,8 @@ MediaWindow::_FindNodes(media_type type, uint64 kind, NodeList& into)
for (int32 i = 0; i < node_info_count; i++) {
PRINT(("node : %s, media_addon %i, flavor_id %i\n",
node_info[i].name, node_info[i].addon, node_info[i].flavor_id));
node_info[i].name, (int)node_info[i].addon,
(int)node_info[i].flavor_id));
dormant_node_info* info = new dormant_node_info();
strncpy(info->name, node_info[i].name, B_MEDIA_NAME_LENGTH);
@@ -263,14 +319,22 @@ MediaWindow::_FindNodes(media_type type, uint64 kind, NodeList& into)
NodeListItem*
MediaWindow::_FindNodeListItem(dormant_node_info* info)
{
NodeListItem audioItem(info, MediaListItem::AUDIO_TYPE);
NodeListItem videoItem(info, MediaListItem::VIDEO_TYPE);
NodeListItem::Comparator audioComparator(&audioItem);
NodeListItem::Comparator videoComparator(&videoItem);
for (int32 i = 0; i < fListView->CountItems(); i++) {
MediaListItem* item
= static_cast<MediaListItem*>(fListView->ItemAt(i));
dormant_node_info* itemInfo = item->NodeInfo();
if (itemInfo && itemInfo->addon == info->addon
&& itemInfo->flavor_id == info->flavor_id) {
return dynamic_cast<NodeListItem*>(item);
}
item->Accept(audioComparator);
if (audioComparator.result == 0)
return static_cast<NodeListItem*>(item);
item->Accept(videoComparator);
if (videoComparator.result == 0)
return static_cast<NodeListItem*>(item);
}
return NULL;
}
@@ -313,43 +377,35 @@ MediaWindow::InitWindow()
scrollView->SetExplicitMaxSize(BSize(scrollWidth, B_SIZE_UNSET));
// Create the Views
fBox = new BBox("background", B_WILL_DRAW | B_FRAME_EVENTS,
B_PLAIN_BORDER);
SetLayout(new BGroupLayout(B_HORIZONTAL));
GetLayout()->AddView(fBox);
// StringViews
fTitleView = new BSeparatorView(B_HORIZONTAL, B_FANCY_BORDER);
fTitleView->SetLabel(B_TRANSLATE("Audio settings"));
fTitleView->SetFont(be_bold_font);
fContentView = new BBox("contentView", B_WILL_DRAW | B_FRAME_EVENTS,
B_NO_BORDER);
fContentLayout = new BCardLayout();
new BView("content view", 0, fContentLayout);
fContentLayout->Owner()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fAudioView = new SettingsView(false);
fVideoView = new SettingsView(true);
fAudioView = new AudioSettingsView();
fContentLayout->AddView(fAudioView);
fVideoView = new VideoSettingsView();
fContentLayout->AddView(fVideoView);
// Layout all views
BGroupView* rightView = new BGroupView(B_VERTICAL, 5);
rightView->GroupLayout()->SetInsets(14, 0, 0, 0);
rightView->GroupLayout()->AddView(fTitleView);
rightView->GroupLayout()->AddView(fContentView);
BGroupLayout* rootLayout = new BGroupLayout(B_HORIZONTAL);
rootLayout->SetInsets(14, 14, 14, 14);
fBox->SetLayout(rootLayout);
rootLayout->AddView(scrollView);
rootLayout->AddView(rightView);
BLayoutBuilder::Group<>(this, B_HORIZONTAL)
.SetInsets(14, 14, 14, 14)
.Add(scrollView)
.AddGroup(B_VERTICAL)
.SetInsets(14, 0, 0, 0)
.Add(fTitleView)
.Add(fContentLayout);
// Start the window
fInitCheck = InitMedia(true);
if (fInitCheck != B_OK) {
PostMessage(B_QUIT_REQUESTED);
} else {
if (IsHidden())
} else if (IsHidden()) {
Show();
}
}
@@ -412,10 +468,10 @@ MediaWindow::InitMedia(bool first)
_AddNodeItems(fAudioOutputs, MediaListItem::AUDIO_TYPE);
_AddNodeItems(fAudioInputs, MediaListItem::AUDIO_TYPE);
fAudioView->AddNodes(fAudioOutputs, false);
fAudioView->AddNodes(fAudioInputs, true);
fVideoView->AddNodes(fVideoOutputs, false);
fVideoView->AddNodes(fVideoInputs, true);
fAudioView->AddOutputNodes(fAudioOutputs);
fAudioView->AddInputNodes(fAudioInputs);
fVideoView->AddOutputNodes(fVideoOutputs);
fVideoView->AddInputNodes(fVideoInputs);
// build our list view
DeviceListItem* audio = new DeviceListItem(B_TRANSLATE("Audio settings"),
@@ -439,43 +495,34 @@ MediaWindow::InitMedia(bool first)
if (roster->GetAudioInput(&default_node) == B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefaultInput(true);
fAudioView->SetDefault(node_info, true);
fAudioView->SetDefaultInput(&node_info);
// this causes our listview to be updated as well
}
if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefaultOutput(true);
fAudioView->SetDefault(node_info, false, outputID);
fAudioView->SetDefaultOutput(&node_info);
fAudioView->SetDefaultChannel(outputID);
// this causes our listview to be updated as well
}
if (roster->GetVideoInput(&default_node)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefaultInput(true);
fVideoView->SetDefault(node_info, true);
fVideoView->SetDefaultInput(&node_info);
// this causes our listview to be updated as well
}
if (roster->GetVideoOutput(&default_node)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefaultOutput(true);
fVideoView->SetDefault(node_info, false);
fVideoView->SetDefaultOutput(&node_info);
// this causes our listview to be updated as well
}
if (first) {
fListView->Select(fListView->IndexOf(mixer));
} else {
if (!fAudioView->fRestartView->IsHidden())
fAudioView->fRestartView->Hide();
if (!fVideoView->fRestartView->IsHidden())
fVideoView->fRestartView->Hide();
fAudioView->RestartRequired(false);
fVideoView->RestartRequired(false);
if (isVideoSelected)
fListView->Select(fListView->IndexOf(video));
@@ -505,15 +552,6 @@ MediaWindow::QuitRequested()
}
void
MediaWindow::FrameResized (float width, float height)
{
// This makes sure our SideBar colours down to the bottom when resized
BRect r;
r = Bounds();
}
// ErrorAlert -- Displays a BAlert Box with a Custom Error or Debug Message
void
ErrorAlert(char* errorMessage) {
@@ -533,98 +571,6 @@ MediaWindow::MessageReceived(BMessage* message)
case ML_INIT_MEDIA:
InitMedia(false);
break;
case ML_DEFAULTOUTPUT_CHANGE:
{
int32 index;
if (message->FindInt32("index", &index)!=B_OK)
break;
Settings2Item* item = static_cast<Settings2Item*>(
fAudioView->fChannelMenu->ItemAt(index));
if (item) {
BMediaRoster* roster = BMediaRoster::Roster();
roster->SetAudioOutput(*item->fInput);
if (fAudioView->fRestartView->IsHidden())
fAudioView->fRestartView->Show();
} else
fprintf(stderr, "Settings2Item not found\n");
}
break;
case ML_DEFAULT_CHANGE:
{
bool isVideo = true;
bool isInput = true;
if (message->FindBool("isVideo", &isVideo)!=B_OK)
break;
if (message->FindBool("isInput", &isInput)!=B_OK)
break;
int32 index;
if (message->FindInt32("index", &index)!=B_OK)
break;
SettingsView* settingsView = isVideo ? fVideoView : fAudioView;
BMenu* menu = isInput ? settingsView->fInputMenu
: settingsView->fOutputMenu;
SettingsItem* item = static_cast<SettingsItem*>(
menu->ItemAt(index));
if (item) {
PRINT(("isVideo %i isInput %i\n", isVideo, isInput));
BMediaRoster* roster = BMediaRoster::Roster();
if (isVideo) {
if (isInput)
roster->SetVideoInput(*item->fInfo);
else
roster->SetVideoOutput(*item->fInfo);
} else {
if (isInput)
roster->SetAudioInput(*item->fInfo);
else {
roster->SetAudioOutput(*item->fInfo);
fAudioView->SetDefault(*item->fInfo, false, 0);
}
}
NodeListItem* oldListItem = NULL;
MediaListItem::media_type mediaType = isVideo ?
MediaListItem::VIDEO_TYPE : MediaListItem::AUDIO_TYPE;
for (int32 j = 0; j < fListView->CountItems(); j++) {
NodeListItem* item = dynamic_cast<NodeListItem*>(
fListView->ItemAt(j));
if (!oldListItem)
continue;
if (oldListItem->Type() != mediaType)
continue;
if (isInput && !oldListItem->IsDefaultInput()) {
oldListItem = item;
break;
} else if (!isInput && oldListItem->IsDefaultOutput()) {
oldListItem = item;
break;
}
}
if (oldListItem && isInput)
oldListItem->SetDefaultInput(false);
else if (oldListItem && !isInput)
oldListItem->SetDefaultOutput(false);
else
fprintf(stderr, "oldListItem not found\n");
NodeListItem* listItem = _FindNodeListItem(item->fInfo);
if (listItem && isInput)
listItem->SetDefaultInput(true);
else if (listItem && !isInput)
listItem->SetDefaultOutput(true);
else
fprintf(stderr, "MediaListItem not found\n");
fListView->Invalidate();
if (settingsView->fRestartView->IsHidden())
settingsView->fRestartView->Show();
} else
fprintf(stderr, "SettingsItem not found\n");
}
break;
case ML_RESTART_MEDIA_SERVER:
{
thread_id thread = spawn_thread(&MediaWindow::RestartMediaServices,
@@ -635,65 +581,21 @@ MediaWindow::MessageReceived(BMessage* message)
resume_thread(thread);
break;
}
case ML_SHOW_VOLUME_CONTROL:
{
BDeskbar deskbar;
if (fAudioView->fVolumeCheckBox->Value() == B_CONTROL_ON) {
BEntry entry("/bin/desklink", true);
int32 id;
entry_ref ref;
status_t status = entry.GetRef(&ref);
if (status == B_OK)
status = deskbar.AddItem(&ref, &id);
if (status != B_OK) {
fprintf(stderr, B_TRANSLATE(
"Couldn't add volume control in Deskbar: %s\n"),
strerror(status));
}
} else {
status_t status = deskbar.RemoveItem("MediaReplicant");
if (status != B_OK) {
fprintf(stderr, B_TRANSLATE(
"Couldn't remove volume control in Deskbar: %s\n"),
strerror(status));
}
}
break;
}
case ML_ENABLE_REAL_TIME:
{
bool isVideo = true;
if (message->FindBool("isVideo", &isVideo) != B_OK)
break;
SettingsView* settingsView = isVideo ? fVideoView : fAudioView;
uint32 flags;
uint32 realtimeFlag = isVideo
? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO;
BMediaRoster* roster = BMediaRoster::Roster();
roster->GetRealtimeFlags(&flags);
if (settingsView->fRealtimeCheckBox->Value() == B_CONTROL_ON)
flags |= realtimeFlag;
else
flags &= ~realtimeFlag;
roster->SetRealtimeFlags(flags);
}
break;
case B_MEDIA_WEB_CHANGED:
case ML_SELECTED_NODE:
{
PRINT_OBJECT(*message);
{
PRINT_OBJECT(*message);
MediaListItem* item = static_cast<MediaListItem*>(
fListView->ItemAt(fListView->CurrentSelection()));
if (!item)
break;
MediaListItem* item = static_cast<MediaListItem*>(
fListView->ItemAt(fListView->CurrentSelection()));
if (!item)
break;
fCurrentNode.SetTo(NULL);
_ClearParamView();
item->AlterWindow(this);
}
fCurrentNode.SetTo(NULL);
_ClearParamView();
item->AlterWindow(this);
break;
}
case B_SOME_APP_LAUNCHED:
{
PRINT_OBJECT(*message);
@@ -791,13 +693,18 @@ MediaWindow::UpdateProgress(int stage, const char * message, void * cookie)
void
MediaWindow::_ClearParamView()
{
BView* child = fContentView->ChildAt(0);
if (child)
child->RemoveSelf();
if (child != fVideoView && child != fAudioView)
delete child;
delete fParamWeb;
fParamWeb = NULL;
BLayoutItem* item = fContentLayout->VisibleItem();
if (!item)
return;
BView* view = item->View();
if (view != fVideoView && view != fAudioView) {
fContentLayout->RemoveItem(item);
delete item;
delete view;
delete fParamWeb;
fParamWeb = NULL;
}
}
@@ -810,17 +717,16 @@ MediaWindow::_MakeParamView()
fParamWeb = NULL;
BMediaRoster* roster = BMediaRoster::Roster();
if (roster->GetParameterWebFor(fCurrentNode, &fParamWeb) == B_OK) {
BView* paramView = BMediaTheme::ViewFor(fParamWeb);
BRect hint(fContentLayout->Frame());
BView* paramView = BMediaTheme::ViewFor(fParamWeb, &hint);
if (paramView) {
fContentView->AddChild(paramView);
paramView->ResizeTo(1, 1);
// make sure we don't get stuck with a very large
// paramView
fContentLayout->AddView(paramView);
fContentLayout->SetVisibleItem(fContentLayout->CountItems() - 1);
return;
}
}
_MakeEmptyParamView();
}
@@ -840,7 +746,8 @@ MediaWindow::_MakeEmptyParamView()
stringView->SetExplicitAlignment(centered);
stringView->SetAlignment(B_ALIGN_CENTER);
fContentView->AddChild(stringView);
fContentLayout->AddView(stringView);
fContentLayout->SetVisibleItem(fContentLayout->CountItems() - 1);
rgb_color panel = stringView->LowColor();
stringView->SetHighColor(tint_color(panel,
+14 -9
View File
@@ -16,7 +16,6 @@
#define __MEDIAWINDOWS_H__
#include <Box.h>
#include <ListView.h>
#include <MediaAddOn.h>
#include <ParameterWeb.h>
@@ -34,6 +33,7 @@
#define SETTINGS_FILE "MediaPrefs Settings"
class BCardLayout;
class BSeparatorView;
// struct dormant_node_info;
@@ -46,15 +46,21 @@ public:
status_t InitCheck();
// methods to be called by MediaListItems...
void SelectNode(dormant_node_info* node);
void SelectNode(const dormant_node_info* node);
void SelectAudioSettings(const char* title);
void SelectVideoSettings(const char* title);
void SelectAudioMixer(const char* title);
// methods to be called by SettingsViews...
void UpdateInputListItem(
MediaListItem::media_type type,
const dormant_node_info* node);
void UpdateOutputListItem(
MediaListItem::media_type type,
const dormant_node_info* node);
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
virtual void FrameResized(float width, float height);
private:
@@ -83,7 +89,7 @@ private:
struct SmartNode {
SmartNode(const BMessenger& notifyHandler);
~SmartNode();
void SetTo(dormant_node_info* node);
void SetTo(const dormant_node_info* node);
void SetTo(const media_node& node);
bool IsSet();
operator media_node();
@@ -94,12 +100,11 @@ private:
BMessenger fMessenger;
};
BBox* fBox;
BListView* fListView;
BSeparatorView* fTitleView;
BView* fContentView;
SettingsView* fAudioView;
SettingsView* fVideoView;
BCardLayout* fContentLayout;
AudioSettingsView* fAudioView;
VideoSettingsView* fVideoView;
SmartNode fCurrentNode;
BParameterWeb* fParamWeb;