diff --git a/src/preferences/media/Media.cpp b/src/preferences/media/Media.cpp index c222fbb269..52d9213a10 100644 --- a/src/preferences/media/Media.cpp +++ b/src/preferences/media/Media.cpp @@ -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)); } diff --git a/src/preferences/media/Media.h b/src/preferences/media/Media.h index 9bf5427223..5a4aa8747b 100644 --- a/src/preferences/media/Media.h +++ b/src/preferences/media/Media.h @@ -26,6 +26,7 @@ public: status_t InitCheck(); private: + MediaIcons fIcons; MediaWindow* fWindow; }; diff --git a/src/preferences/media/MediaIcons.cpp b/src/preferences/media/MediaIcons.cpp index 9ed2426849..984ce9b4fd 100644 --- a/src/preferences/media/MediaIcons.cpp +++ b/src/preferences/media/MediaIcons.cpp @@ -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); } diff --git a/src/preferences/media/MediaIcons.h b/src/preferences/media/MediaIcons.h index 100193816c..1c8eb8c909 100644 --- a/src/preferences/media/MediaIcons.h +++ b/src/preferences/media/MediaIcons.h @@ -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); }; diff --git a/src/preferences/media/MediaListItem.cpp b/src/preferences/media/MediaListItem.cpp index 4d0e85fc30..c5cf0b1998 100644 --- a/src/preferences/media/MediaListItem.cpp +++ b/src/preferences/media/MediaListItem.cpp @@ -12,173 +12,384 @@ // Created : June 25, 2003 // // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ - - #include "MediaListItem.h" #include +#include #include #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(firstArg); - const MediaListItem* item2 - = *static_cast(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); } diff --git a/src/preferences/media/MediaListItem.h b/src/preferences/media/MediaListItem.h index 67beff6e9f..591e1459db 100644 --- a/src/preferences/media/MediaListItem.h +++ b/src/preferences/media/MediaListItem.h @@ -20,50 +20,150 @@ #include +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__ */ diff --git a/src/preferences/media/MediaWindow.cpp b/src/preferences/media/MediaWindow.cpp index 07f37b7cfa..70f532f9f2 100644 --- a/src/preferences/media/MediaWindow.cpp +++ b/src/preferences/media/MediaWindow.cpp @@ -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; jCountItems(); j++) { + for (int32 i = 0; i < fListView->CountItems(); i++) { MediaListItem* item - = static_cast(fListView->ItemAt(j)); - if (item->fInfo && item->fInfo->addon == info->addon - && item->fInfo->flavor_id == info->flavor_id) { - return item; - break; + = static_cast(fListView->ItemAt(i)); + dormant_node_info* itemInfo = item->NodeInfo(); + if (itemInfo && itemInfo->addon == info->addon + && itemInfo->flavor_id == info->flavor_id) { + return dynamic_cast(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( + NodeListItem* item = dynamic_cast( 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)); +} + diff --git a/src/preferences/media/MediaWindow.h b/src/preferences/media/MediaWindow.h index 5ebb85bf45..543f2bcd11 100644 --- a/src/preferences/media/MediaWindow.h +++ b/src/preferences/media/MediaWindow.h @@ -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; };