* With the help of Stippi's "I Will Survive" article, the VolumeControl
replicant should now handle media server restarts, or late starts gracefully. * This fixed ticket #4002. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31322 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5b60969c5c
commit
da30b4bf83
@ -17,8 +17,7 @@
|
||||
#include <ParameterWeb.h>
|
||||
|
||||
|
||||
MixerControl::MixerControl(int32 volumeWhich, float* _value,
|
||||
const char** _error)
|
||||
MixerControl::MixerControl(int32 volumeWhich)
|
||||
:
|
||||
fVolumeWhich(volumeWhich),
|
||||
fGainMediaNode(media_node::null),
|
||||
@ -28,12 +27,28 @@ MixerControl::MixerControl(int32 volumeWhich, float* _value,
|
||||
fMax(0.0f),
|
||||
fStep(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MixerControl::~MixerControl()
|
||||
{
|
||||
_Disconnect();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error)
|
||||
{
|
||||
fVolumeWhich = volumeWhich;
|
||||
|
||||
_Disconnect();
|
||||
|
||||
bool retrying = false;
|
||||
|
||||
status_t err = B_OK;
|
||||
/* BMediaRoster::Roster() doesn't set it if all is ok */
|
||||
status_t status = B_OK;
|
||||
// BMediaRoster::Roster() doesn't set it if all is ok
|
||||
const char* errorString = NULL;
|
||||
BMediaRoster* roster = BMediaRoster::Roster(&err);
|
||||
BMediaRoster* roster = BMediaRoster::Roster(&status);
|
||||
|
||||
retry:
|
||||
// Here we release the BMediaRoster once if we can't access the system
|
||||
@ -49,22 +64,22 @@ retry:
|
||||
roster->Quit();
|
||||
}
|
||||
snooze(10000);
|
||||
roster = BMediaRoster::Roster(&err);
|
||||
roster = BMediaRoster::Roster(&status);
|
||||
}
|
||||
|
||||
if (roster && err == B_OK) {
|
||||
|
||||
if (roster != NULL && status == B_OK) {
|
||||
switch (volumeWhich) {
|
||||
case VOLUME_USE_MIXER:
|
||||
err = roster->GetAudioMixer(&fGainMediaNode);
|
||||
status = roster->GetAudioMixer(&fGainMediaNode);
|
||||
break;
|
||||
case VOLUME_USE_PHYS_OUTPUT:
|
||||
err = roster->GetAudioOutput(&fGainMediaNode);
|
||||
status = roster->GetAudioOutput(&fGainMediaNode);
|
||||
break;
|
||||
}
|
||||
if (err == B_OK) {
|
||||
err = roster->GetParameterWebFor(fGainMediaNode, &fParameterWeb);
|
||||
if (err == B_OK) {
|
||||
// Finding the Mixer slider in the audio output ParameterWeb
|
||||
if (status == B_OK) {
|
||||
status = roster->GetParameterWebFor(fGainMediaNode, &fParameterWeb);
|
||||
if (status == B_OK) {
|
||||
// Finding the Mixer slider in the audio output ParameterWeb
|
||||
int32 numParams = fParameterWeb->CountParameters();
|
||||
BParameter* p = NULL;
|
||||
bool foundMixerLabel = false;
|
||||
@ -102,11 +117,14 @@ retry:
|
||||
if (!strcmp(p->Kind(), B_MASTER_GAIN)) {
|
||||
for (; i < numParams; i++) {
|
||||
p = fParamWeb->ParameterAt(i);
|
||||
if (strcmp(p->Kind(), B_MASTER_GAIN)) p=NULL;
|
||||
else break;
|
||||
if (strcmp(p->Kind(), B_MASTER_GAIN))
|
||||
p = NULL;
|
||||
else
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} else p = NULL;
|
||||
} else
|
||||
p = NULL;
|
||||
#endif
|
||||
p = NULL;
|
||||
}
|
||||
@ -149,7 +167,7 @@ retry:
|
||||
errorString = "No Media Roster";
|
||||
}
|
||||
|
||||
if (err != B_OK)
|
||||
if (status != B_OK)
|
||||
fGainMediaNode = media_node::null;
|
||||
|
||||
if (errorString) {
|
||||
@ -159,16 +177,15 @@ retry:
|
||||
}
|
||||
if (fMixerParameter == NULL && _value != NULL)
|
||||
*_value = 0;
|
||||
|
||||
return errorString == NULL;
|
||||
}
|
||||
|
||||
|
||||
MixerControl::~MixerControl()
|
||||
bool
|
||||
MixerControl::Connected()
|
||||
{
|
||||
delete fParameterWeb;
|
||||
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL && fGainMediaNode != media_node::null)
|
||||
roster->ReleaseNode(fGainMediaNode);
|
||||
return fGainMediaNode != media_node::null;
|
||||
}
|
||||
|
||||
|
||||
@ -220,3 +237,17 @@ MixerControl::ChangeVolumeBy(float value)
|
||||
SetVolume(volume + value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MixerControl::_Disconnect()
|
||||
{
|
||||
delete fParameterWeb;
|
||||
fParameterWeb = NULL;
|
||||
fMixerParameter = NULL;
|
||||
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL && fGainMediaNode != media_node::null)
|
||||
roster->ReleaseNode(fGainMediaNode);
|
||||
|
||||
fGainMediaNode = media_node::null;
|
||||
}
|
||||
|
@ -23,11 +23,13 @@ class BContinuousParameter;
|
||||
|
||||
class MixerControl {
|
||||
public:
|
||||
MixerControl(int32 volumeWhich,
|
||||
float* _value = NULL,
|
||||
const char** _error = NULL);
|
||||
MixerControl(int32 volumeWhich);
|
||||
~MixerControl();
|
||||
|
||||
bool Connect(int32 volumeWhich, float* _value = NULL,
|
||||
const char** _error = NULL);
|
||||
bool Connected();
|
||||
|
||||
int32 VolumeWhich() const;
|
||||
float Volume() const;
|
||||
|
||||
@ -40,6 +42,8 @@ public:
|
||||
media_node GainNode() { return fGainMediaNode; }
|
||||
|
||||
private:
|
||||
void _Disconnect();
|
||||
|
||||
int32 fVolumeWhich;
|
||||
media_node fGainMediaNode;
|
||||
BParameterWeb* fParameterWeb;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <Beep.h>
|
||||
#include <ControlLook.h>
|
||||
#include <Dragger.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <Roster.h>
|
||||
|
||||
#include <AppMisc.h>
|
||||
@ -28,17 +29,23 @@
|
||||
#include "VolumeWindow.h"
|
||||
|
||||
|
||||
static const char* kMediaServerSignature = "application/x-vnd.Be.media-server";
|
||||
static const char* kAddOnServerSignature = "application/x-vnd.Be.addon-host";
|
||||
|
||||
static const uint32 kMsgReconnectVolume = 'rcms';
|
||||
|
||||
|
||||
VolumeControl::VolumeControl(int32 volumeWhich, bool beep, BMessage* message)
|
||||
: BSlider("VolumeControl", "Volume", message, 0, 1, B_HORIZONTAL),
|
||||
fMixerControl(new MixerControl(volumeWhich)),
|
||||
fBeep(beep),
|
||||
fSnapping(false)
|
||||
fSnapping(false),
|
||||
fConnectRetries(0)
|
||||
{
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
SetBarThickness(ceilf((fontHeight.ascent + fontHeight.descent) * 0.7));
|
||||
|
||||
_InitVolume(volumeWhich);
|
||||
|
||||
BRect rect(Bounds());
|
||||
rect.top = rect.bottom - 7;
|
||||
rect.left = rect.right - 7;
|
||||
@ -49,7 +56,10 @@ VolumeControl::VolumeControl(int32 volumeWhich, bool beep, BMessage* message)
|
||||
|
||||
|
||||
VolumeControl::VolumeControl(BMessage* archive)
|
||||
: BSlider(archive)
|
||||
: BSlider(archive),
|
||||
fMixerControl(NULL),
|
||||
fSnapping(false),
|
||||
fConnectRetries(0)
|
||||
{
|
||||
if (archive->FindBool("beep", &fBeep) != B_OK)
|
||||
fBeep = false;
|
||||
@ -58,7 +68,7 @@ VolumeControl::VolumeControl(BMessage* archive)
|
||||
if (archive->FindInt32("volume which", &volumeWhich) != B_OK)
|
||||
volumeWhich = VOLUME_USE_MIXER;
|
||||
|
||||
_InitVolume(volumeWhich);
|
||||
fMixerControl = new MixerControl(volumeWhich);
|
||||
}
|
||||
|
||||
|
||||
@ -109,10 +119,16 @@ VolumeControl::AttachedToWindow()
|
||||
else
|
||||
SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
||||
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL && fMixerControl->GainNode() != media_node::null) {
|
||||
roster->StartWatching(this, fMixerControl->GainNode(),
|
||||
B_MEDIA_NEW_PARAMETER_VALUE);
|
||||
be_roster->StartWatching(this, B_REQUEST_LAUNCHED | B_REQUEST_QUIT);
|
||||
|
||||
_ConnectVolume();
|
||||
|
||||
if (!fMixerControl->Connected()) {
|
||||
// Wait a bit, and try again - the media server might not have been
|
||||
// ready yet
|
||||
BMessage reconnect(kMsgReconnectVolume);
|
||||
BMessageRunner::StartSending(this, &reconnect, 1000000LL, 1);
|
||||
fConnectRetries = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,11 +136,9 @@ VolumeControl::AttachedToWindow()
|
||||
void
|
||||
VolumeControl::DetachedFromWindow()
|
||||
{
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL && fMixerControl->GainNode() != media_node::null) {
|
||||
roster->StopWatching(this, fMixerControl->GainNode(),
|
||||
B_MEDIA_NEW_PARAMETER_VALUE);
|
||||
}
|
||||
_DisconnectVolume();
|
||||
|
||||
be_roster->StopWatching(this);
|
||||
}
|
||||
|
||||
|
||||
@ -267,6 +281,53 @@ VolumeControl::MessageReceived(BMessage* msg)
|
||||
"OK"))->Go(NULL);
|
||||
break;
|
||||
|
||||
case B_SOME_APP_LAUNCHED:
|
||||
case B_SOME_APP_QUIT:
|
||||
{
|
||||
const char* signature;
|
||||
if (msg->FindString("be:signature", &signature) != B_OK)
|
||||
break;
|
||||
|
||||
bool isMediaServer = !strcmp(signature, kMediaServerSignature);
|
||||
bool isAddOnServer = !strcmp(signature, kAddOnServerSignature);
|
||||
if (isMediaServer)
|
||||
fMediaServerRunning = msg->what == B_SOME_APP_LAUNCHED;
|
||||
if (isAddOnServer)
|
||||
fAddOnServerRunning = msg->what == B_SOME_APP_LAUNCHED;
|
||||
|
||||
if (isMediaServer || isAddOnServer) {
|
||||
if (!fMediaServerRunning && !fAddOnServerRunning) {
|
||||
// No media server around
|
||||
SetLabel("No media server running");
|
||||
SetEnabled(false);
|
||||
} else if (fMediaServerRunning && fAddOnServerRunning) {
|
||||
// HACK!
|
||||
// quit our now invalid instance of the media roster
|
||||
// so that before new nodes are created,
|
||||
// we get a new roster
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL) {
|
||||
roster->Lock();
|
||||
roster->Quit();
|
||||
}
|
||||
|
||||
BMessage reconnect(kMsgReconnectVolume);
|
||||
BMessageRunner::StartSending(this, &reconnect, 1000000LL, 1);
|
||||
fConnectRetries = 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgReconnectVolume:
|
||||
_ConnectVolume();
|
||||
if (!fMixerControl->Connected() && --fConnectRetries > 1) {
|
||||
BMessage reconnect(kMsgReconnectVolume);
|
||||
BMessageRunner::StartSending(this, &reconnect,
|
||||
6000000LL / fConnectRetries, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BView::MessageReceived(msg);
|
||||
}
|
||||
@ -324,11 +385,24 @@ VolumeControl::UpdateText() const
|
||||
|
||||
|
||||
void
|
||||
VolumeControl::_InitVolume(int32 volumeWhich)
|
||||
VolumeControl::_DisconnectVolume()
|
||||
{
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL && fMixerControl->GainNode() != media_node::null) {
|
||||
roster->StopWatching(this, fMixerControl->GainNode(),
|
||||
B_MEDIA_NEW_PARAMETER_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeControl::_ConnectVolume()
|
||||
{
|
||||
_DisconnectVolume();
|
||||
|
||||
const char* errorString = NULL;
|
||||
float volume = 0.0;
|
||||
fMixerControl = new MixerControl(volumeWhich, &volume, &errorString);
|
||||
fMixerControl->Connect(fMixerControl->VolumeWhich(), &volume, &errorString);
|
||||
|
||||
if (errorString != NULL) {
|
||||
SetLabel(errorString);
|
||||
@ -337,6 +411,12 @@ VolumeControl::_InitVolume(int32 volumeWhich)
|
||||
SetLabel("Volume");
|
||||
SetLimits((int32)floorf(fMixerControl->Minimum()),
|
||||
(int32)ceilf(fMixerControl->Maximum()));
|
||||
|
||||
BMediaRoster* roster = BMediaRoster::CurrentRoster();
|
||||
if (roster != NULL && fMixerControl->GainNode() != media_node::null) {
|
||||
roster->StartWatching(this, fMixerControl->GainNode(),
|
||||
B_MEDIA_NEW_PARAMETER_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
SetEnabled(errorString == NULL);
|
||||
@ -355,10 +435,10 @@ VolumeControl::_PointForValue(int32 value) const
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
return ceilf(1.0f * (value - min) / (max - min)
|
||||
* (BarFrame().Width() - 2) + BarFrame().left + 1);
|
||||
} else {
|
||||
return ceilf(BarFrame().top - 1.0f * (value - min) / (max - min)
|
||||
* BarFrame().Height());
|
||||
}
|
||||
|
||||
return ceilf(BarFrame().top - 1.0f * (value - min) / (max - min)
|
||||
* BarFrame().Height());
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,7 +42,8 @@ protected:
|
||||
virtual const char* UpdateText() const;
|
||||
|
||||
private:
|
||||
void _InitVolume(int32 volumeWhich);
|
||||
void _DisconnectVolume();
|
||||
void _ConnectVolume();
|
||||
bool _IsReplicant() const;
|
||||
float _PointForValue(int32 value) const;
|
||||
|
||||
@ -54,6 +55,10 @@ private:
|
||||
bool fSnapping;
|
||||
float fMinSnap;
|
||||
float fMaxSnap;
|
||||
|
||||
int32 fConnectRetries;
|
||||
bool fMediaServerRunning;
|
||||
bool fAddOnServerRunning;
|
||||
};
|
||||
|
||||
#endif // VOLUME_SLIDER_H
|
||||
|
Loading…
Reference in New Issue
Block a user