In Media preflet:

* Refactor MediaListItem into four/five classes:
	* MediaListItem : abstract base class which provides an interface for
		MediaWindow and MediaListItem subclasses
	* NodeListItem : list item for media nodes
	* DeviceListItem : list item for audio/video settings (device selection)
	* MixerListItem : list item for the audio-mixer
	* MediaListItem::Renderer : does the drawing of MediaListItems, which supply
		render paramaters via a 'SetRenderParamaters()' method.
* Comparison of MediaListItems (for sorting) is done via double-dispatch
* MediaListItem provides a pure virtual AlterWindow() method, which removes the
	burden of distinguishing between different behaviours from MediaWindow.
* Add methods to MediaWindow for the MediaListItems to call in their
	AlterWindow() implementation, eg. SelectNode()
* Seperate code into these methods, as well as a few private utility methods.
* Add a RAII-style 'SmartNode' nested class for MediaWindow, which handles
	watching/unwatching allocating/deallocating of media_nodes


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39433 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alex Wilson
2010-11-15 08:45:11 +00:00
parent f1c707c4a2
commit e7b9974180
8 changed files with 769 additions and 299 deletions
+2
View File
@@ -22,6 +22,7 @@
Media::Media()
:
BApplication("application/x-vnd.Haiku-Media"),
fIcons(),
fWindow(NULL)
{
BRect rect(32, 64, 637, 462);
@@ -57,6 +58,7 @@ Media::Media()
}
fWindow = new MediaWindow(rect);
MediaListItem::SetIcons(&fIcons);
be_roster->StartWatching(BMessenger(this));
}
+1
View File
@@ -26,6 +26,7 @@ public:
status_t InitCheck();
private:
MediaIcons fIcons;
MediaWindow* fWindow;
};
+15 -9
View File
@@ -15,14 +15,20 @@
const BRect MediaIcons::sBounds(0, 0, 15, 15);
MediaIcons::IconSet::IconSet()
:
inputIcon(MediaIcons::sBounds, B_CMAP8),
outputIcon(MediaIcons::sBounds, B_CMAP8)
{
}
MediaIcons::MediaIcons()
:
devicesIcon(sBounds, B_CMAP8),
mixerIcon(sBounds, B_CMAP8),
tvIcon(sBounds, B_CMAP8),
camIcon(sBounds, B_CMAP8),
micIcon(sBounds, B_CMAP8),
speakerIcon(sBounds, B_CMAP8)
mixerIcon(sBounds, B_CMAP8)
{
app_info info;
be_app->GetAppInfo(&info);
@@ -32,10 +38,10 @@ MediaIcons::MediaIcons()
_LoadBitmap(&resources, devices_icon, &devicesIcon);
_LoadBitmap(&resources, mixer_icon, &mixerIcon);
_LoadBitmap(&resources, tv_icon, &tvIcon);
_LoadBitmap(&resources, cam_icon, &camIcon);
_LoadBitmap(&resources, mic_icon, &micIcon);
_LoadBitmap(&resources, speaker_icon, &speakerIcon);
_LoadBitmap(&resources, tv_icon, &videoIcons.outputIcon);
_LoadBitmap(&resources, cam_icon, &videoIcons.inputIcon);
_LoadBitmap(&resources, mic_icon, &audioIcons.inputIcon);
_LoadBitmap(&resources, speaker_icon, &audioIcons.outputIcon);
}
+14 -6
View File
@@ -14,18 +14,26 @@ class BResources;
struct MediaIcons {
MediaIcons();
struct IconSet {
IconSet();
BBitmap inputIcon;
BBitmap outputIcon;
};
BBitmap devicesIcon;
BBitmap mixerIcon;
BBitmap tvIcon;
BBitmap camIcon;
BBitmap micIcon;
BBitmap speakerIcon;
BRect IconRectAt(const BPoint& topLeft);
private:
IconSet audioIcons;
IconSet videoIcons;
static BRect IconRectAt(const BPoint& topLeft);
static const BRect sBounds;
private:
void _LoadBitmap(BResources* resources, int32 id,
BBitmap* bitmap);
};
+348 -137
View File
@@ -12,173 +12,384 @@
// Created : June 25, 2003
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#include "MediaListItem.h"
#include <string.h>
#include <MediaAddOn.h>
#include <View.h>
#include "MediaIcons.h"
#include "MediaWindow.h"
#define kITEM_MARGIN 1
#define kITEM_MARGIN 1
#define GREATER_THAN -1
#define LESS_THAN 1
MediaListItem::MediaListItem(dormant_node_info* info, uint32 level,
bool isVideo, MediaIcons* icons, uint32 modifiers)
:
BListItem(level),
fInfo(info),
fLabel(info->name),
fIsAudioMixer(false),
fIsVideo(isVideo),
fIsDefaultInput(false),
fIsDefaultOutput(false),
fIcons(icons)
{
SetHeight(16 + kITEM_MARGIN);
}
MediaIcons* MediaListItem::sIcons = NULL;
MediaListItem::MediaListItem(const char* label, uint32 level,
bool isVideo, MediaIcons* icons, uint32 modifiers)
:
BListItem(level),
fInfo(NULL),
fLabel(label),
fIsAudioMixer(false),
fIsVideo(isVideo),
fIsDefaultInput(false),
fIsDefaultOutput(false),
fIcons(icons)
{
SetHeight(16 + kITEM_MARGIN);
}
struct MediaListItem::Renderer {
Renderer()
:
fTitle(NULL),
fPrimaryIcon(NULL),
fSecondaryIcon(NULL),
fDoubleInsets(true),
fSelected(false)
{
}
MediaListItem::~MediaListItem()
{
}
//MediaListItem - DrawItem
void
MediaListItem::DrawItem(BView* owner, BRect frame, bool complete)
{
rgb_color kHighlight = { 140,140,140,0 };
rgb_color kBlack = { 0,0,0,0 };
BRect r(frame);
if (IsSelected() || complete) {
rgb_color color;
if (IsSelected()) {
color = kHighlight;
} else {
color = owner->ViewColor();
// The first icon added is drawn next to the label,
// the second is drawn to the right of the label.
void AddIcon(BBitmap* icon)
{
if (!fPrimaryIcon)
fPrimaryIcon = icon;
else {
fSecondaryIcon = fPrimaryIcon;
fPrimaryIcon = icon;
}
owner->SetHighColor(color);
owner->SetLowColor(color);
owner->FillRect(r);
owner->SetHighColor(kBlack);
} else {
owner->SetLowColor(owner->ViewColor());
}
void SetTitle(const char* title)
{
fTitle = title;
}
void SetSelected(bool selected)
{
fSelected = selected;
}
// set whether or not to leave enough room for two icons,
// defaults to true.
void UseDoubleInset(bool doubleInset)
{
fDoubleInsets = doubleInset;
}
frame.left += 4;
BRect iconFrame(fIcons->IconRectAt(BPoint(frame.left, frame.top + 1)));
BBitmap* icon = &fIcons->devicesIcon;
if (OutlineLevel() == 0 || (fIsDefaultInput && fIsDefaultOutput)) {
if (fIsDefaultInput && fIsVideo)
icon = &fIcons->camIcon;
else if (fIsDefaultInput && !fIsVideo)
icon = &fIcons->micIcon;
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(icon, iconFrame);
owner->SetDrawingMode(B_OP_COPY);
}
iconFrame.OffsetBy(16, 0);
if (fIsDefaultInput || fIsDefaultOutput || fIsAudioMixer) {
if (fIsAudioMixer)
icon = &fIcons->mixerIcon;
else if (fIsDefaultOutput) {
if (fIsVideo)
icon = &fIcons->tvIcon;
else
icon = &fIcons->speakerIcon;
} else {
if (fIsVideo)
icon = &fIcons->camIcon;
else
icon = &fIcons->speakerIcon;
}
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(icon, iconFrame);
owner->SetDrawingMode(B_OP_COPY);
}
frame.left += 16 * (OutlineLevel() + 1);
owner->SetHighColor(kBlack);
void Render(BView* onto, BRect frame, bool complete = false)
{
const rgb_color lowColor = onto->LowColor();
const rgb_color highColor = onto->HighColor();
const rgb_color kBlack = {0, 0, 0, 255};
BFont font = be_plain_font;
font_height fontInfo;
font.GetHeight(&fontInfo);
float lineHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
owner->SetFont(&font);
owner->MovePenTo(frame.left + 8, frame.top
+ ((frame.Height() - (lineHeight)) / 2)
+ (fontInfo.ascent + fontInfo.descent) - 1);
owner->DrawString(fLabel);
}
if (fSelected || complete) {
if (fSelected)
onto->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT));
onto->FillRect(frame, B_SOLID_LOW);
}
frame.left += 4;
frame.top += kITEM_MARGIN;
BRect iconFrame(MediaIcons::IconRectAt(frame.LeftTop() + BPoint(1, 0)));
onto->SetDrawingMode(B_OP_OVER);
if (fPrimaryIcon && !fDoubleInsets) {
onto->DrawBitmap(fPrimaryIcon, iconFrame);
frame.left = iconFrame.right + 1;
} else if (fSecondaryIcon) {
onto->DrawBitmap(fSecondaryIcon, iconFrame);
}
iconFrame = MediaIcons::IconRectAt(iconFrame.RightTop() + BPoint(1, 0));
if (fDoubleInsets && fPrimaryIcon) {
onto->DrawBitmap(fPrimaryIcon, iconFrame);
frame.left = iconFrame.right + 1;
}
onto->SetDrawingMode(B_OP_COPY);
onto->SetHighColor(kBlack);
BFont font = be_plain_font;
font_height fontInfo;
font.GetHeight(&fontInfo);
float lineHeight = fontInfo.ascent + fontInfo.descent
+ fontInfo.leading;
onto->SetFont(&font);
onto->MovePenTo(frame.left + 8, frame.top
+ ((frame.Height() - (lineHeight)) / 2)
+ (fontInfo.ascent + fontInfo.descent) - 1);
onto->DrawString(fTitle);
onto->SetHighColor(highColor);
onto->SetLowColor(lowColor);
}
private:
const char* fTitle;
BBitmap* fPrimaryIcon;
BBitmap* fSecondaryIcon;
bool fDoubleInsets;
bool fSelected;
};
void
MediaListItem::SetDefault(bool isDefault, bool isInput)
MediaListItem::MediaListItem()
:
BListItem((uint32)0)
{
if (isInput)
fIsDefaultInput = isDefault;
else
fIsDefaultOutput = isDefault;
}
void
MediaListItem::SetAudioMixer(bool isAudioMixer)
{
fIsAudioMixer = isAudioMixer;
}
void
MediaListItem::Update(BView* owner, const BFont* finfo)
void
MediaListItem::Update(BView* owner, const BFont* font)
{
// we need to override the update method so we can make sure our
// list item size doesn't change
BListItem::Update(owner, finfo);
if ((Height() < 16 + kITEM_MARGIN)) {
SetHeight(16 + kITEM_MARGIN);
BListItem::Update(owner, font);
float iconHeight = MediaIcons::sBounds.Height() + 1;
if ((Height() < iconHeight + kITEM_MARGIN * 2)) {
SetHeight(iconHeight + kITEM_MARGIN * 2);
}
}
int
MediaListItem::Compare(const void* firstArg, const void* secondArg)
void
MediaListItem::DrawItem(BView* owner, BRect frame, bool complete)
{
const MediaListItem* item1
= *static_cast<const MediaListItem* const*>(firstArg);
const MediaListItem* item2
= *static_cast<const MediaListItem* const*>(secondArg);
if (item1->fIsVideo != item2->fIsVideo)
return item1->fIsVideo ? 1 : -1;
if (item1->OutlineLevel() != item2->OutlineLevel())
return item1->OutlineLevel() > item2->OutlineLevel() ? 1 : -1;
if (item1->fIsAudioMixer != item2->fIsAudioMixer)
return item2->fIsAudioMixer ? 1 : -1;
return strcmp(item1->fLabel, item2->fLabel);
Renderer renderer;
renderer.SetSelected(IsSelected());
renderer.SetTitle(Label());
SetRenderParameters(renderer);
renderer.Render(owner, frame, complete);
}
int
MediaListItem::Compare(const void* itemOne, const void* itemTwo)
{
MediaListItem* firstItem = *(MediaListItem**)itemOne;
MediaListItem* secondItem = *(MediaListItem**)itemTwo;
return firstItem->CompareWith(secondItem);
}
// #pragma mark - NodeListItem
NodeListItem::NodeListItem(dormant_node_info* node, media_type type)
:
MediaListItem(),
fNodeInfo(node),
fIsAudioMixer(false),
fMediaType(type),
fIsDefaultInput(false),
fIsDefaultOutput(false)
{
}
void
NodeListItem::SetRenderParameters(MediaListItem::Renderer& renderer)
{
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);
}
}
const char*
NodeListItem::Label()
{
return fNodeInfo->name;
}
void
NodeListItem::SetMediaType(media_type type)
{
fMediaType = type;
}
void
NodeListItem::SetDefaultOutput(bool isDefault)
{
fIsDefaultOutput = isDefault;
}
void
NodeListItem::SetDefaultInput(bool isDefault)
{
fIsDefaultInput = isDefault;
}
void
NodeListItem::AlterWindow(MediaWindow* window)
{
window->SelectNode(fNodeInfo);
}
int
NodeListItem::CompareWith(MediaListItem* item)
{
return item->CompareWith(this) * -1;
}
int
NodeListItem::CompareWith(NodeListItem* item)
{
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)
{
if (fMediaType != deviceItem->Type())
return fMediaType == AUDIO_TYPE ? GREATER_THAN : LESS_THAN;
else
return LESS_THAN;
}
int
NodeListItem::CompareWith(AudioMixerListItem* item)
{
return LESS_THAN;
}
// #pragma mark - DeviceListItem
DeviceListItem::DeviceListItem(const char* title,
MediaListItem::media_type type)
:
MediaListItem(),
fTitle(title),
fMediaType(type)
{
}
int
DeviceListItem::CompareWith(MediaListItem* item)
{
return item->CompareWith(this) * -1;
}
int
DeviceListItem::CompareWith(NodeListItem* item)
{
// let NodeListItem do the work
return item->CompareWith(this) * -1;
}
int
DeviceListItem::CompareWith(DeviceListItem* item)
{
if (fMediaType == MediaListItem::AUDIO_TYPE)
return GREATER_THAN;
return LESS_THAN;
}
int
DeviceListItem::CompareWith(AudioMixerListItem* item)
{
// let AudioMixerListItem do the work too!
return item->CompareWith(this) * -1;
}
void
DeviceListItem::SetRenderParameters(Renderer& renderer)
{
renderer.AddIcon(&Icons()->devicesIcon);
renderer.UseDoubleInset(false);
}
void
DeviceListItem::AlterWindow(MediaWindow* window)
{
if (fMediaType == MediaListItem::AUDIO_TYPE)
window->SelectAudioSettings(fTitle);
else
window->SelectVideoSettings(fTitle);
}
// #pragma mark - AudioMixerListItem
AudioMixerListItem::AudioMixerListItem(const char* title)
:
MediaListItem(),
fTitle(title)
{
}
void
AudioMixerListItem::AlterWindow(MediaWindow* window)
{
window->SelectAudioMixer(fTitle);
}
int
AudioMixerListItem::CompareWith(MediaListItem* item)
{
return item->CompareWith(this) * -1;
}
int
AudioMixerListItem::CompareWith(NodeListItem* item)
{
return GREATER_THAN;
}
int
AudioMixerListItem::CompareWith(DeviceListItem* item)
{
if (item->Type() == AUDIO_TYPE)
return LESS_THAN;
return GREATER_THAN;
}
int
AudioMixerListItem::CompareWith(AudioMixerListItem* item)
{
return 0;
}
void
AudioMixerListItem::SetRenderParameters(Renderer& renderer)
{
renderer.AddIcon(&Icons()->mixerIcon);
}
+125 -25
View File
@@ -20,50 +20,150 @@
#include <MediaAddOn.h>
struct dormant_node_info;
class MediaIcons;
class MediaWindow;
class AudioMixerListItem;
class DeviceListItem;
class NodeListItem;
class MediaListItem : public BListItem {
public:
MediaListItem(dormant_node_info* info,
uint32 level, bool isVideo,
MediaIcons* icons, uint32 modifiers = 0);
MediaListItem(const char* label, uint32 level,
bool isVideo, MediaIcons* icons,
uint32 modifiers=0);
virtual ~MediaListItem();
MediaListItem();
virtual void AlterWindow(MediaWindow* window) = 0;
enum media_type {
AUDIO_TYPE,
VIDEO_TYPE
};
virtual void Update(BView* owner, const BFont* font);
virtual void DrawItem(BView* owner, BRect frame,
bool complete = false);
void SetDefault(bool isDefaultInput, bool isInput);
void SetAudioMixer(bool isAudioMixer);
bool IsDefault(bool isInput)
{
return isInput ? fIsDefaultInput : fIsDefaultOutput;
}
// TODO: refactor and remove this:
virtual dormant_node_info* NodeInfo() = 0;
bool IsAudioMixer() { return fIsAudioMixer; }
bool IsVideo() { return fIsVideo; }
const char* GetLabel() { return fLabel; }
virtual const char* Label() = 0;
static MediaIcons* Icons() {return sIcons;}
static void SetIcons(MediaIcons* icons) {sIcons = icons;}
dormant_node_info* fInfo;
static int Compare(const void* itemOne,
const void* itemTwo);
static int Compare(const void* firstArg,
const void* secondArg);
// use double dispatch for comparison,
// returning item->CompareWith(this) * -1
// -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;
protected:
struct Renderer;
virtual void SetRenderParameters(Renderer& renderer) = 0;
private:
const char* fLabel;
static MediaIcons* sIcons;
};
class NodeListItem : public MediaListItem {
public:
NodeListItem(dormant_node_info* node,
media_type type);
void SetMediaType(MediaListItem::media_type type);
void SetDefaultOutput(bool isDefault);
bool IsDefaultOutput() {return fIsDefaultOutput;}
void SetDefaultInput(bool isDefault);
bool IsDefaultInput() {return fIsDefaultInput;}
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);
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(NodeListItem* item);
virtual int CompareWith(DeviceListItem* item);
virtual int CompareWith(AudioMixerListItem* item);
private:
virtual void SetRenderParameters(Renderer& renderer);
dormant_node_info* fNodeInfo;
bool fIsAudioMixer;
bool fIsVideo;
media_type fMediaType;
bool fIsDefaultInput;
bool fIsDefaultOutput;
//dormant_node_info fNodeInfo;
MediaIcons* fIcons;
};
class DeviceListItem : public MediaListItem {
public:
DeviceListItem(const char* title,
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 int CompareWith(MediaListItem* item);
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(NodeListItem* item);
virtual int CompareWith(DeviceListItem* item);
virtual int CompareWith(AudioMixerListItem* item);
private:
virtual void SetRenderParameters(Renderer& renderer);
const char* fTitle;
media_type fMediaType;
};
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 int CompareWith(MediaListItem* item);
// -1 : < item; 0 : == item; 1 : > item
virtual int CompareWith(NodeListItem* item);
virtual int CompareWith(DeviceListItem* item);
virtual int CompareWith(AudioMixerListItem* item);
private:
virtual void SetRenderParameters(Renderer& renderer);
const char* fTitle;
};
#endif /* __MEDIALISTITEM_H__ */
+232 -114
View File
@@ -44,18 +44,92 @@ const uint32 ML_SELECTED_NODE = 'MlSN';
const uint32 ML_INIT_MEDIA = 'MlIM';
MediaWindow::SmartNode::SmartNode(const BMessenger& notifyHandler)
:
fNode(NULL),
fMessenger(notifyHandler)
{
}
MediaWindow::SmartNode::~SmartNode()
{
_FreeNode();
}
void
MediaWindow::SmartNode::SetTo(dormant_node_info* info)
{
_FreeNode();
if (!info)
return;
fNode = new media_node();
// TODO: check error codes
BMediaRoster* roster = BMediaRoster::Roster();
media_node_id node_id;
if (roster->GetInstancesFor(info->addon, info->flavor_id, &node_id) == B_OK)
roster->GetNodeFor(node_id, fNode);
else
roster->InstantiateDormantNode(*info, fNode, B_FLAVOR_IS_GLOBAL);
roster->StartWatching(fMessenger, *fNode, B_MEDIA_WILDCARD);
}
void
MediaWindow::SmartNode::SetTo(const media_node& node)
{
_FreeNode();
fNode = new media_node(node);
BMediaRoster* roster = BMediaRoster::Roster();
roster->StartWatching(fMessenger, *fNode, B_MEDIA_WILDCARD);
}
bool
MediaWindow::SmartNode::IsSet()
{
return fNode != NULL;
}
MediaWindow::SmartNode::operator media_node()
{
if (fNode)
return *fNode;
media_node node;
return node;
}
void
MediaWindow::SmartNode::_FreeNode()
{
if (!IsSet())
return;
// TODO: check error codes
BMediaRoster* roster = BMediaRoster::Roster();
roster->StopWatching(fMessenger, *fNode, B_MEDIA_WILDCARD);
roster->ReleaseNode(*fNode);
delete fNode;
fNode = NULL;
}
// MediaWindow - Constructor
MediaWindow::MediaWindow(BRect frame)
:
BWindow (frame, B_TRANSLATE("Media"), B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
fCurrentNode(NULL),
fCurrentNode(BMessenger(this)),
fParamWeb(NULL),
fAudioInputs(5, true),
fAudioOutputs(5, true),
fVideoInputs(5, true),
fVideoOutputs(5, true),
fIcons(),
fAlert(NULL),
fInitCheck(B_OK)
{
@@ -73,10 +147,9 @@ MediaWindow::InitCheck()
MediaWindow::~MediaWindow()
{
_EmptyNodeLists();
BMediaRoster* roster = BMediaRoster::Roster();
if (roster && fCurrentNode)
roster->ReleaseNode(*fCurrentNode);
_ClearParamView();
delete fVideoView;
delete fAudioView;
char buffer[512];
BRect rect = Frame();
@@ -95,6 +168,43 @@ MediaWindow::~MediaWindow()
}
void
MediaWindow::SelectNode(dormant_node_info* node)
{
fCurrentNode.SetTo(node);
_MakeParamView();
fTitleView->SetLabel(node->name);
}
void
MediaWindow::SelectAudioSettings(const char* title)
{
fContentView->AddChild(fAudioView);
fTitleView->SetLabel(title);
}
void
MediaWindow::SelectVideoSettings(const char* title)
{
fContentView->AddChild(fVideoView);
fTitleView->SetLabel(title);
}
void
MediaWindow::SelectAudioMixer(const char* title)
{
media_node mixerNode;
BMediaRoster* roster = BMediaRoster::Roster();
roster->GetAudioMixer(&mixerNode);
fCurrentNode.SetTo(mixerNode);
_MakeParamView();
fTitleView->SetLabel(title);
}
void
MediaWindow::_FindNodes()
{
@@ -150,16 +260,16 @@ MediaWindow::_FindNodes(media_type type, uint64 kind, NodeList& into)
}
MediaListItem *
MediaWindow::FindMediaListItem(dormant_node_info* info)
NodeListItem*
MediaWindow::_FindNodeListItem(dormant_node_info* info)
{
for (int32 j = 0; j<fListView->CountItems(); j++) {
for (int32 i = 0; i < fListView->CountItems(); i++) {
MediaListItem* item
= static_cast<MediaListItem *>(fListView->ItemAt(j));
if (item->fInfo && item->fInfo->addon == info->addon
&& item->fInfo->flavor_id == info->flavor_id) {
return item;
break;
= 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);
}
}
return NULL;
@@ -167,13 +277,13 @@ MediaWindow::FindMediaListItem(dormant_node_info* info)
void
MediaWindow::_AddNodeItems(NodeList &list, bool isVideo)
MediaWindow::_AddNodeItems(NodeList &list, MediaListItem::media_type type)
{
int32 count = list.CountItems();
for (int32 i = 0; i < count; i++) {
dormant_node_info* info = list.ItemAt(i);
if (!FindMediaListItem(info))
fListView->AddItem(new MediaListItem(info, 1, isVideo, &fIcons));
if (!_FindNodeListItem(info))
fListView->AddItem(new NodeListItem(info, type));
}
}
@@ -297,10 +407,10 @@ MediaWindow::InitMedia(bool first)
// Add video nodes first. They might have an additional audio
// output or input, but still should be listed as video node.
_AddNodeItems(fVideoOutputs, true);
_AddNodeItems(fVideoInputs, true);
_AddNodeItems(fAudioOutputs, false);
_AddNodeItems(fAudioInputs, false);
_AddNodeItems(fVideoOutputs, MediaListItem::VIDEO_TYPE);
_AddNodeItems(fVideoInputs, MediaListItem::VIDEO_TYPE);
_AddNodeItems(fAudioOutputs, MediaListItem::AUDIO_TYPE);
_AddNodeItems(fAudioInputs, MediaListItem::AUDIO_TYPE);
fAudioView->AddNodes(fAudioOutputs, false);
fAudioView->AddNodes(fAudioInputs, true);
@@ -308,18 +418,16 @@ MediaWindow::InitMedia(bool first)
fVideoView->AddNodes(fVideoInputs, true);
// build our list view
MediaListItem* audio = new MediaListItem(B_TRANSLATE("Audio settings"), 0,
false, &fIcons);
DeviceListItem* audio = new DeviceListItem(B_TRANSLATE("Audio settings"),
MediaListItem::AUDIO_TYPE);
fListView->AddItem(audio);
MediaListItem* video = new MediaListItem(B_TRANSLATE("Video settings"), 0,
true, &fIcons);
MediaListItem* video = new DeviceListItem(B_TRANSLATE("Video settings"),
MediaListItem::VIDEO_TYPE);
fListView->AddItem(video);
MediaListItem* mixer = new MediaListItem(B_TRANSLATE("Audio mixer"),
1, false, &fIcons);
MediaListItem* mixer = new AudioMixerListItem(B_TRANSLATE("Audio mixer"));
fListView->AddItem(mixer);
mixer->SetAudioMixer(true);
fListView->SortItems(&MediaListItem::Compare);
@@ -331,33 +439,33 @@ MediaWindow::InitMedia(bool first)
if (roster->GetAudioInput(&default_node) == B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefault(true, true);
item->SetDefaultInput(true);
fAudioView->SetDefault(node_info, true);
}
if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefault(true, false);
item->SetDefaultOutput(true);
fAudioView->SetDefault(node_info, false, outputID);
}
if (roster->GetVideoInput(&default_node)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefault(true, true);
item->SetDefaultInput(true);
fVideoView->SetDefault(node_info, true);
}
if (roster->GetVideoOutput(&default_node)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info);
NodeListItem* item = _FindNodeListItem(&node_info);
if (item)
item->SetDefault(true, false);
item->SetDefaultOutput(true);
fVideoView->SetDefault(node_info, false);
}
@@ -391,10 +499,7 @@ bool
MediaWindow::QuitRequested()
{
// stop watching the MediaRoster
BMediaRoster* roster = BMediaRoster::CurrentRoster();
if (roster && fCurrentNode) {
roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
}
fCurrentNode.SetTo(NULL);
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
@@ -480,24 +585,37 @@ MediaWindow::MessageReceived(BMessage* message)
}
}
MediaListItem* oldListItem = NULL;
NodeListItem* oldListItem = NULL;
MediaListItem::media_type mediaType = isVideo ?
MediaListItem::VIDEO_TYPE : MediaListItem::AUDIO_TYPE;
for (int32 j = 0; j < fListView->CountItems(); j++) {
oldListItem = static_cast<MediaListItem*>(
NodeListItem* item = dynamic_cast<NodeListItem*>(
fListView->ItemAt(j));
if (oldListItem->fInfo
&& oldListItem->IsVideo() == isVideo
&& oldListItem->IsDefault(isInput))
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)
oldListItem->SetDefault(false, isInput);
if (oldListItem && isInput)
oldListItem->SetDefaultInput(false);
else if (oldListItem && !isInput)
oldListItem->SetDefaultOutput(false);
else
fprintf(stderr, "oldListItem not found\n");
MediaListItem* listItem = FindMediaListItem(item->fInfo);
if (listItem) {
listItem->SetDefault(true, isInput);
} else
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();
@@ -570,70 +688,10 @@ MediaWindow::MessageReceived(BMessage* message)
fListView->ItemAt(fListView->CurrentSelection()));
if (!item)
break;
BMediaRoster* roster = BMediaRoster::Roster();
if (fCurrentNode) {
// stop watching the MediaRoster
roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
roster->ReleaseNode(*fCurrentNode);
}
fCurrentNode = NULL;
BView* paramView = fContentView->ChildAt(0);
if (paramView!=NULL) {
fContentView->RemoveChild(paramView);
}
paramView = NULL;
if (fParamWeb)
delete fParamWeb;
fParamWeb = NULL;
fTitleView->SetLabel(item->GetLabel());
if (item->OutlineLevel() == 0) {
if (item->IsVideo())
fContentView->AddChild(fVideoView);
else
fContentView->AddChild(fAudioView);
} else {
if (!fCurrentNode)
fCurrentNode = new media_node();
media_node_id node_id;
if (item->IsAudioMixer())
roster->GetAudioMixer(fCurrentNode);
else if (roster->GetInstancesFor(item->fInfo->addon, item->fInfo->flavor_id, &node_id)!=B_OK)
roster->InstantiateDormantNode(*(item->fInfo), fCurrentNode, B_FLAVOR_IS_GLOBAL);
else
roster->GetNodeFor(node_id, fCurrentNode);
if (roster->GetParameterWebFor(*fCurrentNode, &fParamWeb)==B_OK
&& (paramView = BMediaTheme::PreferredTheme()->ViewFor(fParamWeb)) != NULL) {
fContentView->AddChild(paramView);
paramView->ResizeTo(1, 1);
// make sure we don't get stuck with a very large
// paramView
roster->StartWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
} else {
delete fParamWeb;
fParamWeb = NULL;
BStringView* stringView = new BStringView("noControls",
B_TRANSLATE("This hardware has no controls."));
BSize unlimited(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
stringView->SetExplicitMaxSize(unlimited);
BAlignment centered(B_ALIGN_HORIZONTAL_CENTER,
B_ALIGN_VERTICAL_CENTER);
stringView->SetExplicitAlignment(centered);
stringView->SetAlignment(B_ALIGN_CENTER);
fContentView->AddChild(stringView);
rgb_color panel = stringView->LowColor();
stringView->SetHighColor(tint_color(panel,
B_DISABLED_LABEL_TINT));
}
}
fCurrentNode.SetTo(NULL);
_ClearParamView();
item->AlterWindow(this);
}
break;
case B_SOME_APP_LAUNCHED:
@@ -729,3 +787,63 @@ MediaWindow::UpdateProgress(int stage, const char * message, void * cookie)
return true;
}
void
MediaWindow::_ClearParamView()
{
BView* child = fContentView->ChildAt(0);
if (child)
child->RemoveSelf();
if (child != fVideoView && child != fAudioView)
delete child;
delete fParamWeb;
fParamWeb = NULL;
}
void
MediaWindow::_MakeParamView()
{
if (!fCurrentNode.IsSet())
return;
fParamWeb = NULL;
BMediaRoster* roster = BMediaRoster::Roster();
if (roster->GetParameterWebFor(fCurrentNode, &fParamWeb) == B_OK) {
BView* paramView = BMediaTheme::ViewFor(fParamWeb);
if (paramView) {
fContentView->AddChild(paramView);
paramView->ResizeTo(1, 1);
// make sure we don't get stuck with a very large
// paramView
return;
}
}
_MakeEmptyParamView();
}
void
MediaWindow::_MakeEmptyParamView()
{
fParamWeb = NULL;
BStringView* stringView = new BStringView("noControls",
B_TRANSLATE("This hardware has no controls."));
BSize unlimited(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
stringView->SetExplicitMaxSize(unlimited);
BAlignment centered(B_ALIGN_HORIZONTAL_CENTER,
B_ALIGN_VERTICAL_CENTER);
stringView->SetExplicitAlignment(centered);
stringView->SetAlignment(B_ALIGN_CENTER);
fContentView->AddChild(stringView);
rgb_color panel = stringView->LowColor();
stringView->SetHighColor(tint_color(panel,
B_DISABLED_LABEL_TINT));
}
+32 -8
View File
@@ -43,10 +43,18 @@ class MediaWindow : public BWindow
public:
MediaWindow(BRect frame);
~MediaWindow();
status_t InitCheck();
// methods to be called by MediaListItems...
void SelectNode(dormant_node_info* node);
void SelectAudioSettings(const char* title);
void SelectVideoSettings(const char* title);
void SelectAudioMixer(const char* title);
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
virtual void FrameResized(float width, float height);
status_t InitCheck();
private:
@@ -56,16 +64,35 @@ private:
status_t InitMedia(bool first);
void _FindNodes();
void _FindNodes(media_type type, uint64 kind,
NodeList& into);
void _AddNodeItems(NodeList& from, bool isVideo);
NodeList& into);
void _AddNodeItems(NodeList &from,
MediaListItem::media_type type);
void _EmptyNodeLists();
MediaListItem* FindMediaListItem(dormant_node_info* info);
NodeListItem* _FindNodeListItem(dormant_node_info* info);
void InitWindow();
static status_t RestartMediaServices(void* data);
static bool UpdateProgress(int stage, const char * message,
void * cookie);
void _ClearParamView();
void _MakeParamView();
void _MakeEmptyParamView();
struct SmartNode {
SmartNode(const BMessenger& notifyHandler);
~SmartNode();
void SetTo(dormant_node_info* node);
void SetTo(const media_node& node);
bool IsSet();
operator media_node();
private:
void _FreeNode();
media_node* fNode;
BMessenger fMessenger;
};
BBox* fBox;
BListView* fListView;
@@ -74,7 +101,7 @@ private:
SettingsView* fAudioView;
SettingsView* fVideoView;
media_node* fCurrentNode;
SmartNode fCurrentNode;
BParameterWeb* fParamWeb;
@@ -83,9 +110,6 @@ private:
NodeList fVideoInputs;
NodeList fVideoOutputs;
MediaIcons fIcons;
MediaAlert* fAlert;
status_t fInitCheck;
};