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:
@@ -57,8 +57,8 @@ Media::Media()
|
||||
}
|
||||
}
|
||||
|
||||
fWindow = new MediaWindow(rect);
|
||||
MediaListItem::SetIcons(&fIcons);
|
||||
fWindow = new MediaWindow(rect);
|
||||
|
||||
be_roster->StartWatching(BMessenger(this));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user