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() Media::Media()
: :
BApplication("application/x-vnd.Haiku-Media"), BApplication("application/x-vnd.Haiku-Media"),
fIcons(),
fWindow(NULL) fWindow(NULL)
{ {
BRect rect(32, 64, 637, 462); BRect rect(32, 64, 637, 462);
@@ -57,6 +58,7 @@ Media::Media()
} }
fWindow = new MediaWindow(rect); fWindow = new MediaWindow(rect);
MediaListItem::SetIcons(&fIcons);
be_roster->StartWatching(BMessenger(this)); be_roster->StartWatching(BMessenger(this));
} }
+1
View File
@@ -26,6 +26,7 @@ public:
status_t InitCheck(); status_t InitCheck();
private: private:
MediaIcons fIcons;
MediaWindow* fWindow; MediaWindow* fWindow;
}; };
+15 -9
View File
@@ -15,14 +15,20 @@
const BRect MediaIcons::sBounds(0, 0, 15, 15); const BRect MediaIcons::sBounds(0, 0, 15, 15);
MediaIcons::IconSet::IconSet()
:
inputIcon(MediaIcons::sBounds, B_CMAP8),
outputIcon(MediaIcons::sBounds, B_CMAP8)
{
}
MediaIcons::MediaIcons() MediaIcons::MediaIcons()
: :
devicesIcon(sBounds, B_CMAP8), devicesIcon(sBounds, B_CMAP8),
mixerIcon(sBounds, B_CMAP8), mixerIcon(sBounds, B_CMAP8)
tvIcon(sBounds, B_CMAP8),
camIcon(sBounds, B_CMAP8),
micIcon(sBounds, B_CMAP8),
speakerIcon(sBounds, B_CMAP8)
{ {
app_info info; app_info info;
be_app->GetAppInfo(&info); be_app->GetAppInfo(&info);
@@ -32,10 +38,10 @@ MediaIcons::MediaIcons()
_LoadBitmap(&resources, devices_icon, &devicesIcon); _LoadBitmap(&resources, devices_icon, &devicesIcon);
_LoadBitmap(&resources, mixer_icon, &mixerIcon); _LoadBitmap(&resources, mixer_icon, &mixerIcon);
_LoadBitmap(&resources, tv_icon, &tvIcon); _LoadBitmap(&resources, tv_icon, &videoIcons.outputIcon);
_LoadBitmap(&resources, cam_icon, &camIcon); _LoadBitmap(&resources, cam_icon, &videoIcons.inputIcon);
_LoadBitmap(&resources, mic_icon, &micIcon); _LoadBitmap(&resources, mic_icon, &audioIcons.inputIcon);
_LoadBitmap(&resources, speaker_icon, &speakerIcon); _LoadBitmap(&resources, speaker_icon, &audioIcons.outputIcon);
} }
+14 -6
View File
@@ -14,18 +14,26 @@ class BResources;
struct MediaIcons { struct MediaIcons {
MediaIcons(); MediaIcons();
struct IconSet {
IconSet();
BBitmap inputIcon;
BBitmap outputIcon;
};
BBitmap devicesIcon; BBitmap devicesIcon;
BBitmap mixerIcon; BBitmap mixerIcon;
BBitmap tvIcon;
BBitmap camIcon;
BBitmap micIcon;
BBitmap speakerIcon;
BRect IconRectAt(const BPoint& topLeft); IconSet audioIcons;
private: IconSet videoIcons;
static BRect IconRectAt(const BPoint& topLeft);
static const BRect sBounds; static const BRect sBounds;
private:
void _LoadBitmap(BResources* resources, int32 id, void _LoadBitmap(BResources* resources, int32 id,
BBitmap* bitmap); BBitmap* bitmap);
}; };
+332 -121
View File
@@ -12,173 +12,384 @@
// Created : June 25, 2003 // Created : June 25, 2003
// //
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
#include "MediaListItem.h" #include "MediaListItem.h"
#include <string.h> #include <string.h>
#include <MediaAddOn.h>
#include <View.h> #include <View.h>
#include "MediaIcons.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, MediaIcons* MediaListItem::sIcons = NULL;
bool isVideo, MediaIcons* icons, uint32 modifiers)
struct MediaListItem::Renderer {
Renderer()
: :
BListItem(level), fTitle(NULL),
fInfo(info), fPrimaryIcon(NULL),
fLabel(info->name), fSecondaryIcon(NULL),
fIsAudioMixer(false), fDoubleInsets(true),
fIsVideo(isVideo), fSelected(false)
fIsDefaultInput(false), {
fIsDefaultOutput(false),
fIcons(icons)
{
SetHeight(16 + kITEM_MARGIN);
}
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);
}
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();
} }
owner->SetHighColor(color);
owner->SetLowColor(color); // The first icon added is drawn next to the label,
owner->FillRect(r); // the second is drawn to the right of the label.
owner->SetHighColor(kBlack); void AddIcon(BBitmap* icon)
} else { {
owner->SetLowColor(owner->ViewColor()); if (!fPrimaryIcon)
fPrimaryIcon = icon;
else {
fSecondaryIcon = fPrimaryIcon;
fPrimaryIcon = icon;
}
}
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;
}
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};
if (fSelected || complete) {
if (fSelected)
onto->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT));
onto->FillRect(frame, B_SOLID_LOW);
} }
frame.left += 4; frame.left += 4;
BRect iconFrame(fIcons->IconRectAt(BPoint(frame.left, frame.top + 1))); frame.top += kITEM_MARGIN;
BRect iconFrame(MediaIcons::IconRectAt(frame.LeftTop() + BPoint(1, 0)));
BBitmap* icon = &fIcons->devicesIcon; onto->SetDrawingMode(B_OP_OVER);
if (OutlineLevel() == 0 || (fIsDefaultInput && fIsDefaultOutput)) { if (fPrimaryIcon && !fDoubleInsets) {
if (fIsDefaultInput && fIsVideo) onto->DrawBitmap(fPrimaryIcon, iconFrame);
icon = &fIcons->camIcon; frame.left = iconFrame.right + 1;
else if (fIsDefaultInput && !fIsVideo) } else if (fSecondaryIcon) {
icon = &fIcons->micIcon; onto->DrawBitmap(fSecondaryIcon, iconFrame);
}
iconFrame = MediaIcons::IconRectAt(iconFrame.RightTop() + BPoint(1, 0));
owner->SetDrawingMode(B_OP_OVER); if (fDoubleInsets && fPrimaryIcon) {
owner->DrawBitmap(icon, iconFrame); onto->DrawBitmap(fPrimaryIcon, iconFrame);
owner->SetDrawingMode(B_OP_COPY); frame.left = iconFrame.right + 1;
} }
iconFrame.OffsetBy(16, 0); onto->SetDrawingMode(B_OP_COPY);
if (fIsDefaultInput || fIsDefaultOutput || fIsAudioMixer) { onto->SetHighColor(kBlack);
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);
BFont font = be_plain_font; BFont font = be_plain_font;
font_height fontInfo; font_height fontInfo;
font.GetHeight(&fontInfo); font.GetHeight(&fontInfo);
float lineHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading; float lineHeight = fontInfo.ascent + fontInfo.descent
owner->SetFont(&font); + fontInfo.leading;
owner->MovePenTo(frame.left + 8, frame.top onto->SetFont(&font);
onto->MovePenTo(frame.left + 8, frame.top
+ ((frame.Height() - (lineHeight)) / 2) + ((frame.Height() - (lineHeight)) / 2)
+ (fontInfo.ascent + fontInfo.descent) - 1); + (fontInfo.ascent + fontInfo.descent) - 1);
owner->DrawString(fLabel); onto->DrawString(fTitle);
onto->SetHighColor(highColor);
onto->SetLowColor(lowColor);
}
private:
const char* fTitle;
BBitmap* fPrimaryIcon;
BBitmap* fSecondaryIcon;
bool fDoubleInsets;
bool fSelected;
};
MediaListItem::MediaListItem()
:
BListItem((uint32)0)
{
} }
void void
MediaListItem::SetDefault(bool isDefault, bool isInput) 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, font);
float iconHeight = MediaIcons::sBounds.Height() + 1;
if ((Height() < iconHeight + kITEM_MARGIN * 2)) {
SetHeight(iconHeight + kITEM_MARGIN * 2);
}
}
void
MediaListItem::DrawItem(BView* owner, BRect frame, bool complete)
{
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)
{ {
if (isInput)
fIsDefaultInput = isDefault;
else
fIsDefaultOutput = isDefault; fIsDefaultOutput = isDefault;
} }
void void
MediaListItem::SetAudioMixer(bool isAudioMixer) NodeListItem::SetDefaultInput(bool isDefault)
{ {
fIsAudioMixer = isAudioMixer; fIsDefaultInput = isDefault;
} }
void void
MediaListItem::Update(BView* owner, const BFont* finfo) NodeListItem::AlterWindow(MediaWindow* window)
{ {
// we need to override the update method so we can make sure our window->SelectNode(fNodeInfo);
// list item size doesn't change
BListItem::Update(owner, finfo);
if ((Height() < 16 + kITEM_MARGIN)) {
SetHeight(16 + kITEM_MARGIN);
}
} }
int int
MediaListItem::Compare(const void* firstArg, const void* secondArg) NodeListItem::CompareWith(MediaListItem* item)
{ {
const MediaListItem* item1 return item->CompareWith(this) * -1;
= *static_cast<const MediaListItem* const*>(firstArg); }
const MediaListItem* item2
= *static_cast<const MediaListItem* const*>(secondArg);
int
if (item1->fIsVideo != item2->fIsVideo) NodeListItem::CompareWith(NodeListItem* item)
return item1->fIsVideo ? 1 : -1; {
if (item1->OutlineLevel() != item2->OutlineLevel()) if (fMediaType != item->fMediaType)
return item1->OutlineLevel() > item2->OutlineLevel() ? 1 : -1; return fMediaType == AUDIO_TYPE ? GREATER_THAN : LESS_THAN;
if (item1->fIsAudioMixer != item2->fIsAudioMixer)
return item2->fIsAudioMixer ? 1 : -1; if (fIsAudioMixer != item->fIsAudioMixer)
return strcmp(item1->fLabel, item2->fLabel); 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);
} }
+123 -23
View File
@@ -20,50 +20,150 @@
#include <MediaAddOn.h> #include <MediaAddOn.h>
struct dormant_node_info;
class MediaIcons; class MediaIcons;
class MediaWindow;
class AudioMixerListItem;
class DeviceListItem;
class NodeListItem;
class MediaListItem : public BListItem { class MediaListItem : public BListItem {
public: public:
MediaListItem(dormant_node_info* info, MediaListItem();
uint32 level, bool isVideo,
MediaIcons* icons, uint32 modifiers = 0); virtual void AlterWindow(MediaWindow* window) = 0;
MediaListItem(const char* label, uint32 level,
bool isVideo, MediaIcons* icons, enum media_type {
uint32 modifiers=0); AUDIO_TYPE,
virtual ~MediaListItem(); VIDEO_TYPE
};
virtual void Update(BView* owner, const BFont* font); virtual void Update(BView* owner, const BFont* font);
virtual void DrawItem(BView* owner, BRect frame, virtual void DrawItem(BView* owner, BRect frame,
bool complete = false); bool complete = false);
void SetDefault(bool isDefaultInput, bool isInput); // TODO: refactor and remove this:
void SetAudioMixer(bool isAudioMixer); virtual dormant_node_info* NodeInfo() = 0;
virtual const char* Label() = 0;
bool IsDefault(bool isInput) static MediaIcons* Icons() {return sIcons;}
{ static void SetIcons(MediaIcons* icons) {sIcons = icons;}
return isInput ? fIsDefaultInput : fIsDefaultOutput;
}
bool IsAudioMixer() { return fIsAudioMixer; } static int Compare(const void* itemOne,
bool IsVideo() { return fIsVideo; } const void* itemTwo);
const char* GetLabel() { return fLabel; }
// 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;
dormant_node_info* fInfo; protected:
struct Renderer;
static int Compare(const void* firstArg, virtual void SetRenderParameters(Renderer& renderer) = 0;
const void* secondArg);
private: 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 fIsAudioMixer;
bool fIsVideo; media_type fMediaType;
bool fIsDefaultInput; bool fIsDefaultInput;
bool fIsDefaultOutput; 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__ */ #endif /* __MEDIALISTITEM_H__ */
+232 -114
View File
@@ -44,18 +44,92 @@ const uint32 ML_SELECTED_NODE = 'MlSN';
const uint32 ML_INIT_MEDIA = 'MlIM'; 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 - Constructor
MediaWindow::MediaWindow(BRect frame) 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), B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
fCurrentNode(NULL), fCurrentNode(BMessenger(this)),
fParamWeb(NULL), fParamWeb(NULL),
fAudioInputs(5, true), fAudioInputs(5, true),
fAudioOutputs(5, true), fAudioOutputs(5, true),
fVideoInputs(5, true), fVideoInputs(5, true),
fVideoOutputs(5, true), fVideoOutputs(5, true),
fIcons(),
fAlert(NULL), fAlert(NULL),
fInitCheck(B_OK) fInitCheck(B_OK)
{ {
@@ -73,10 +147,9 @@ MediaWindow::InitCheck()
MediaWindow::~MediaWindow() MediaWindow::~MediaWindow()
{ {
_EmptyNodeLists(); _EmptyNodeLists();
_ClearParamView();
BMediaRoster* roster = BMediaRoster::Roster(); delete fVideoView;
if (roster && fCurrentNode) delete fAudioView;
roster->ReleaseNode(*fCurrentNode);
char buffer[512]; char buffer[512];
BRect rect = Frame(); 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 void
MediaWindow::_FindNodes() MediaWindow::_FindNodes()
{ {
@@ -150,16 +260,16 @@ MediaWindow::_FindNodes(media_type type, uint64 kind, NodeList& into)
} }
MediaListItem * NodeListItem*
MediaWindow::FindMediaListItem(dormant_node_info* info) MediaWindow::_FindNodeListItem(dormant_node_info* info)
{ {
for (int32 j = 0; j<fListView->CountItems(); j++) { for (int32 i = 0; i < fListView->CountItems(); i++) {
MediaListItem* item MediaListItem* item
= static_cast<MediaListItem *>(fListView->ItemAt(j)); = static_cast<MediaListItem*>(fListView->ItemAt(i));
if (item->fInfo && item->fInfo->addon == info->addon dormant_node_info* itemInfo = item->NodeInfo();
&& item->fInfo->flavor_id == info->flavor_id) { if (itemInfo && itemInfo->addon == info->addon
return item; && itemInfo->flavor_id == info->flavor_id) {
break; return dynamic_cast<NodeListItem*>(item);
} }
} }
return NULL; return NULL;
@@ -167,13 +277,13 @@ MediaWindow::FindMediaListItem(dormant_node_info* info)
void void
MediaWindow::_AddNodeItems(NodeList &list, bool isVideo) MediaWindow::_AddNodeItems(NodeList &list, MediaListItem::media_type type)
{ {
int32 count = list.CountItems(); int32 count = list.CountItems();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
dormant_node_info* info = list.ItemAt(i); dormant_node_info* info = list.ItemAt(i);
if (!FindMediaListItem(info)) if (!_FindNodeListItem(info))
fListView->AddItem(new MediaListItem(info, 1, isVideo, &fIcons)); fListView->AddItem(new NodeListItem(info, type));
} }
} }
@@ -297,10 +407,10 @@ MediaWindow::InitMedia(bool first)
// Add video nodes first. They might have an additional audio // Add video nodes first. They might have an additional audio
// output or input, but still should be listed as video node. // output or input, but still should be listed as video node.
_AddNodeItems(fVideoOutputs, true); _AddNodeItems(fVideoOutputs, MediaListItem::VIDEO_TYPE);
_AddNodeItems(fVideoInputs, true); _AddNodeItems(fVideoInputs, MediaListItem::VIDEO_TYPE);
_AddNodeItems(fAudioOutputs, false); _AddNodeItems(fAudioOutputs, MediaListItem::AUDIO_TYPE);
_AddNodeItems(fAudioInputs, false); _AddNodeItems(fAudioInputs, MediaListItem::AUDIO_TYPE);
fAudioView->AddNodes(fAudioOutputs, false); fAudioView->AddNodes(fAudioOutputs, false);
fAudioView->AddNodes(fAudioInputs, true); fAudioView->AddNodes(fAudioInputs, true);
@@ -308,18 +418,16 @@ MediaWindow::InitMedia(bool first)
fVideoView->AddNodes(fVideoInputs, true); fVideoView->AddNodes(fVideoInputs, true);
// build our list view // build our list view
MediaListItem* audio = new MediaListItem(B_TRANSLATE("Audio settings"), 0, DeviceListItem* audio = new DeviceListItem(B_TRANSLATE("Audio settings"),
false, &fIcons); MediaListItem::AUDIO_TYPE);
fListView->AddItem(audio); fListView->AddItem(audio);
MediaListItem* video = new MediaListItem(B_TRANSLATE("Video settings"), 0, MediaListItem* video = new DeviceListItem(B_TRANSLATE("Video settings"),
true, &fIcons); MediaListItem::VIDEO_TYPE);
fListView->AddItem(video); fListView->AddItem(video);
MediaListItem* mixer = new MediaListItem(B_TRANSLATE("Audio mixer"), MediaListItem* mixer = new AudioMixerListItem(B_TRANSLATE("Audio mixer"));
1, false, &fIcons);
fListView->AddItem(mixer); fListView->AddItem(mixer);
mixer->SetAudioMixer(true);
fListView->SortItems(&MediaListItem::Compare); fListView->SortItems(&MediaListItem::Compare);
@@ -331,33 +439,33 @@ MediaWindow::InitMedia(bool first)
if (roster->GetAudioInput(&default_node) == B_OK) { if (roster->GetAudioInput(&default_node) == B_OK) {
roster->GetDormantNodeFor(default_node, &node_info); roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info); NodeListItem* item = _FindNodeListItem(&node_info);
if (item) if (item)
item->SetDefault(true, true); item->SetDefaultInput(true);
fAudioView->SetDefault(node_info, true); fAudioView->SetDefault(node_info, true);
} }
if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) { if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info); roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info); NodeListItem* item = _FindNodeListItem(&node_info);
if (item) if (item)
item->SetDefault(true, false); item->SetDefaultOutput(true);
fAudioView->SetDefault(node_info, false, outputID); fAudioView->SetDefault(node_info, false, outputID);
} }
if (roster->GetVideoInput(&default_node)==B_OK) { if (roster->GetVideoInput(&default_node)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info); roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info); NodeListItem* item = _FindNodeListItem(&node_info);
if (item) if (item)
item->SetDefault(true, true); item->SetDefaultInput(true);
fVideoView->SetDefault(node_info, true); fVideoView->SetDefault(node_info, true);
} }
if (roster->GetVideoOutput(&default_node)==B_OK) { if (roster->GetVideoOutput(&default_node)==B_OK) {
roster->GetDormantNodeFor(default_node, &node_info); roster->GetDormantNodeFor(default_node, &node_info);
MediaListItem* item = FindMediaListItem(&node_info); NodeListItem* item = _FindNodeListItem(&node_info);
if (item) if (item)
item->SetDefault(true, false); item->SetDefaultOutput(true);
fVideoView->SetDefault(node_info, false); fVideoView->SetDefault(node_info, false);
} }
@@ -391,10 +499,7 @@ bool
MediaWindow::QuitRequested() MediaWindow::QuitRequested()
{ {
// stop watching the MediaRoster // stop watching the MediaRoster
BMediaRoster* roster = BMediaRoster::CurrentRoster(); fCurrentNode.SetTo(NULL);
if (roster && fCurrentNode) {
roster->StopWatching(this, *fCurrentNode, B_MEDIA_WILDCARD);
}
be_app->PostMessage(B_QUIT_REQUESTED); be_app->PostMessage(B_QUIT_REQUESTED);
return true; 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++) { for (int32 j = 0; j < fListView->CountItems(); j++) {
oldListItem = static_cast<MediaListItem*>( NodeListItem* item = dynamic_cast<NodeListItem*>(
fListView->ItemAt(j)); fListView->ItemAt(j));
if (oldListItem->fInfo if (!oldListItem)
&& oldListItem->IsVideo() == isVideo continue;
&& oldListItem->IsDefault(isInput)) if (oldListItem->Type() != mediaType)
continue;
if (isInput && !oldListItem->IsDefaultInput()) {
oldListItem = item;
break;
} else if (!isInput && oldListItem->IsDefaultOutput()) {
oldListItem = item;
break; break;
} }
if (oldListItem) }
oldListItem->SetDefault(false, isInput); if (oldListItem && isInput)
oldListItem->SetDefaultInput(false);
else if (oldListItem && !isInput)
oldListItem->SetDefaultOutput(false);
else else
fprintf(stderr, "oldListItem not found\n"); fprintf(stderr, "oldListItem not found\n");
MediaListItem* listItem = FindMediaListItem(item->fInfo); NodeListItem* listItem = _FindNodeListItem(item->fInfo);
if (listItem) { if (listItem && isInput)
listItem->SetDefault(true, isInput); listItem->SetDefaultInput(true);
} else else if (listItem && !isInput)
listItem->SetDefaultOutput(true);
else
fprintf(stderr, "MediaListItem not found\n"); fprintf(stderr, "MediaListItem not found\n");
fListView->Invalidate(); fListView->Invalidate();
@@ -570,70 +688,10 @@ MediaWindow::MessageReceived(BMessage* message)
fListView->ItemAt(fListView->CurrentSelection())); fListView->ItemAt(fListView->CurrentSelection()));
if (!item) if (!item)
break; 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()); fCurrentNode.SetTo(NULL);
_ClearParamView();
if (item->OutlineLevel() == 0) { item->AlterWindow(this);
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));
}
}
} }
break; break;
case B_SOME_APP_LAUNCHED: case B_SOME_APP_LAUNCHED:
@@ -729,3 +787,63 @@ MediaWindow::UpdateProgress(int stage, const char * message, void * cookie)
return true; 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));
}
+31 -7
View File
@@ -43,10 +43,18 @@ class MediaWindow : public BWindow
public: public:
MediaWindow(BRect frame); MediaWindow(BRect frame);
~MediaWindow(); ~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 bool QuitRequested();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void FrameResized(float width, float height); virtual void FrameResized(float width, float height);
status_t InitCheck();
private: private:
@@ -57,16 +65,35 @@ private:
void _FindNodes(); void _FindNodes();
void _FindNodes(media_type type, uint64 kind, void _FindNodes(media_type type, uint64 kind,
NodeList& into); NodeList& into);
void _AddNodeItems(NodeList& from, bool isVideo); void _AddNodeItems(NodeList &from,
MediaListItem::media_type type);
void _EmptyNodeLists(); void _EmptyNodeLists();
MediaListItem* FindMediaListItem(dormant_node_info* info); NodeListItem* _FindNodeListItem(dormant_node_info* info);
void InitWindow(); void InitWindow();
static status_t RestartMediaServices(void* data); static status_t RestartMediaServices(void* data);
static bool UpdateProgress(int stage, const char * message, static bool UpdateProgress(int stage, const char * message,
void * cookie); 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; BBox* fBox;
BListView* fListView; BListView* fListView;
BSeparatorView* fTitleView; BSeparatorView* fTitleView;
@@ -74,7 +101,7 @@ private:
SettingsView* fAudioView; SettingsView* fAudioView;
SettingsView* fVideoView; SettingsView* fVideoView;
media_node* fCurrentNode; SmartNode fCurrentNode;
BParameterWeb* fParamWeb; BParameterWeb* fParamWeb;
@@ -83,9 +110,6 @@ private:
NodeList fVideoInputs; NodeList fVideoInputs;
NodeList fVideoOutputs; NodeList fVideoOutputs;
MediaIcons fIcons;
MediaAlert* fAlert; MediaAlert* fAlert;
status_t fInitCheck; status_t fInitCheck;
}; };