diff --git a/src/bin/desklink/MediaReplicant.cpp b/src/bin/desklink/MediaReplicant.cpp index 6ce5f7c31d..64f3bf4264 100644 --- a/src/bin/desklink/MediaReplicant.cpp +++ b/src/bin/desklink/MediaReplicant.cpp @@ -131,7 +131,6 @@ public: virtual void MouseDown(BPoint point); virtual void Draw(BRect updateRect); virtual void MessageReceived(BMessage* message); - virtual void Pulse(); private: status_t _LaunchByPath(const char* path); @@ -143,6 +142,11 @@ private: void _SaveSettings(); void _Init(); + void _DisconnectMixer(); + status_t _ConnectMixer(); + + MixerControl* fMixerControl; + BBitmap* fIcon; BBitmap* fMutedIcon; VolumeWindow* fVolumeSlider; @@ -179,6 +183,7 @@ MediaReplicant::~MediaReplicant() { delete fIcon; _SaveSettings(); + _DisconnectMixer(); } @@ -208,6 +213,8 @@ MediaReplicant::AttachedToWindow() { AdoptParentColors(); + _ConnectMixer(); + BView::AttachedToWindow(); } @@ -267,13 +274,13 @@ MediaReplicant::MouseDown(BPoint point) where + BPoint(4, 4))); } else if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0) { - MixerControl mixerControl; - if (mixerControl.Connect(fVolumeWhich)) { - mixerControl.SetMute(!fMuted); - fMuted = mixerControl.Mute(); + if (fMixerControl != NULL) { + fMixerControl->SetMute(!fMuted); + fMuted = fMixerControl->Mute(); VolumeToolTip* tip = dynamic_cast(ToolTip()); if (tip != NULL) { tip->SetMuteMessage(fMuted ? B_TRANSLATE("Muted"): NULL); + tip->Update(); ShowToolTip(tip); } Invalidate(); @@ -288,28 +295,6 @@ MediaReplicant::MouseDown(BPoint point) } -void -MediaReplicant::Pulse() -{ - bool setMuted = false; - MixerControl mixerControl; - const char* errorString = NULL; - if (!mixerControl.Connect(fVolumeWhich, NULL, &errorString)) { - fMuted = true; - errorString = NULL; - } else - setMuted = mixerControl.Mute(); - - if (setMuted != fMuted) { - fMuted = setMuted; - VolumeToolTip* tip = dynamic_cast(ToolTip()); - if (tip != NULL) - tip->SetMuteMessage(errorString); - Invalidate(); - } -} - - void MediaReplicant::MessageReceived(BMessage* message) { @@ -350,8 +335,18 @@ MediaReplicant::MessageReceived(BMessage* message) fVolumeWhich = item->IsMarked() ? VOLUME_USE_PHYS_OUTPUT : VOLUME_USE_MIXER; - if (VolumeToolTip* tip = dynamic_cast(ToolTip())) + if (_ConnectMixer() != B_OK + && fVolumeWhich == VOLUME_USE_PHYS_OUTPUT) { + // unable to switch to physical output + item->SetMarked(false); + fVolumeWhich = VOLUME_USE_MIXER; + _ConnectMixer(); + } + + if (VolumeToolTip* tip = dynamic_cast(ToolTip())) { tip->SetWhich(fVolumeWhich); + tip->Update(); + } break; } @@ -359,10 +354,8 @@ MediaReplicant::MessageReceived(BMessage* message) { float deltaY; if (message->FindFloat("be:wheel_delta_y", &deltaY) == B_OK - && deltaY != 0.0) { - MixerControl mixerControl; - mixerControl.Connect(fVolumeWhich); - mixerControl.ChangeVolumeBy(deltaY < 0 ? 6 : -6); + && deltaY != 0.0 && fMixerControl != NULL) { + fMixerControl->ChangeVolumeBy(deltaY < 0 ? 6 : -6); VolumeToolTip* tip = dynamic_cast(ToolTip()); if (tip != NULL) { @@ -373,6 +366,46 @@ MediaReplicant::MessageReceived(BMessage* message) break; } + case B_MEDIA_NEW_PARAMETER_VALUE: + { + if (fMixerControl != NULL && !fMixerControl->Connected()) + return; + + bool setMuted = fMixerControl->Mute(); + if (setMuted != fMuted) { + fMuted = setMuted; + VolumeToolTip* tip = dynamic_cast(ToolTip()); + if (tip != NULL) { + tip->SetMuteMessage(fMuted ? B_TRANSLATE("Muted") : NULL); + tip->Update(); + } + Invalidate(); + } + break; + } + + case B_MEDIA_SERVER_STARTED: + _ConnectMixer(); + break; + + case B_MEDIA_NODE_CREATED: + { + // It's not enough to wait for B_MEDIA_SERVER_STARTED message, as + // the mixer will still be getting loaded by the media server + media_node mixerNode; + media_node_id mixerNodeID; + BMediaRoster* roster = BMediaRoster::CurrentRoster(); + if (roster != NULL + && message->FindInt32("media_node_id",&mixerNodeID) == B_OK + && roster->GetNodeFor(mixerNodeID, &mixerNode) == B_OK) { + if (mixerNode.kind == B_SYSTEM_MIXER) { + _ConnectMixer(); + roster->ReleaseNode(mixerNode); + } + } + break; + } + default: BView::MessageReceived(message); break; @@ -509,6 +542,56 @@ MediaReplicant::_Init() } +void +MediaReplicant::_DisconnectMixer() +{ + BMediaRoster* roster = BMediaRoster::CurrentRoster(); + if (roster == NULL) + return; + + roster->StopWatching(this, B_MEDIA_SERVER_STARTED | B_MEDIA_NODE_CREATED); + + if (fMixerControl->MuteNode() != media_node::null) { + roster->StopWatching(this, fMixerControl->MuteNode(), + B_MEDIA_NEW_PARAMETER_VALUE); + } + + delete fMixerControl; + fMixerControl = NULL; +} + + +status_t +MediaReplicant::_ConnectMixer() +{ + _DisconnectMixer(); + + BMediaRoster* roster = BMediaRoster::Roster(); + if (roster == NULL) + return B_ERROR; + + roster->StartWatching(this, B_MEDIA_SERVER_STARTED | B_MEDIA_NODE_CREATED); + + fMixerControl = new MixerControl(fVolumeWhich); + + const char* errorString = NULL; + float volume = 0.0; + fMixerControl->Connect(fVolumeWhich, &volume, &errorString); + + if (errorString != NULL) { + SetToolTip(errorString); + return B_ERROR; + } + + if (fMixerControl->MuteNode() != media_node::null) { + roster->StartWatching(this, fMixerControl->MuteNode(), + B_MEDIA_NEW_PARAMETER_VALUE); + } + + return B_OK; +} + + // #pragma mark - diff --git a/src/bin/desklink/MixerControl.cpp b/src/bin/desklink/MixerControl.cpp index 81cb36cbd3..cdc6d3ffa7 100644 --- a/src/bin/desklink/MixerControl.cpp +++ b/src/bin/desklink/MixerControl.cpp @@ -23,6 +23,7 @@ MixerControl::MixerControl(int32 volumeWhich) : fVolumeWhich(volumeWhich), fGainMediaNode(media_node::null), + fMuteMediaNode(media_node::null), fParameterWeb(NULL), fMixerParameter(NULL), fMuteParameter(NULL), @@ -74,8 +75,10 @@ MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error) p = fParameterWeb->ParameterAt(i); // assume the mute preceeding master gain control - if (!strcmp(p->Kind(), B_MUTE)) + if (!strcmp(p->Kind(), B_MUTE)) { fMuteParameter = p; + fMuteMediaNode = fMuteParameter->Web()->Node(); + } PRINT(("BParameter[%i]: %s\n", i, p->Name())); if (volumeWhich == VOLUME_USE_MIXER) { @@ -151,8 +154,10 @@ MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error) } else errorString = "Media services not running"; - if (status != B_OK) + if (status != B_OK) { fGainMediaNode = media_node::null; + fMuteMediaNode = media_node::null; + } if (errorString) { fprintf(stderr, "MixerControl: %s.\n", errorString); diff --git a/src/bin/desklink/MixerControl.h b/src/bin/desklink/MixerControl.h index 68fd1254e6..159ee38188 100644 --- a/src/bin/desklink/MixerControl.h +++ b/src/bin/desklink/MixerControl.h @@ -44,12 +44,14 @@ public: float Maximum() const { return fMax; } media_node GainNode() { return fGainMediaNode; } + media_node MuteNode() { return fMuteMediaNode; } private: void _Disconnect(); int32 fVolumeWhich; media_node fGainMediaNode; + media_node fMuteMediaNode; BParameterWeb* fParameterWeb; BContinuousParameter* fMixerParameter; BParameter* fMuteParameter;