[Haiku-commits] r31322 - haiku/trunk/src/bin/desklink

axeld at BerliOS axeld at mail.berlios.de
Tue Jun 30 12:14:54 CEST 2009


Author: axeld
Date: 2009-06-30 12:14:54 +0200 (Tue, 30 Jun 2009)
New Revision: 31322
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31322&view=rev

Modified:
   haiku/trunk/src/bin/desklink/MixerControl.cpp
   haiku/trunk/src/bin/desklink/MixerControl.h
   haiku/trunk/src/bin/desklink/VolumeControl.cpp
   haiku/trunk/src/bin/desklink/VolumeControl.h
Log:
* 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.


Modified: haiku/trunk/src/bin/desklink/MixerControl.cpp
===================================================================
--- haiku/trunk/src/bin/desklink/MixerControl.cpp	2009-06-29 22:38:15 UTC (rev 31321)
+++ haiku/trunk/src/bin/desklink/MixerControl.cpp	2009-06-30 10:14:54 UTC (rev 31322)
@@ -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 @@
 	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 @@
 			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 @@
 					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 @@
 		errorString = "No Media Roster";
 	}
 
-	if (err != B_OK)
+	if (status != B_OK)
 		fGainMediaNode = media_node::null;
 
 	if (errorString) {
@@ -159,16 +177,15 @@
 	}
 	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 @@
 	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;
+}

Modified: haiku/trunk/src/bin/desklink/MixerControl.h
===================================================================
--- haiku/trunk/src/bin/desklink/MixerControl.h	2009-06-29 22:38:15 UTC (rev 31321)
+++ haiku/trunk/src/bin/desklink/MixerControl.h	2009-06-30 10:14:54 UTC (rev 31322)
@@ -23,11 +23,13 @@
 
 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 @@
 			media_node		GainNode() { return fGainMediaNode; }
 
 private:
+			void			_Disconnect();
+
 			int32			fVolumeWhich;
 			media_node		fGainMediaNode;
 			BParameterWeb*	fParameterWeb;

Modified: haiku/trunk/src/bin/desklink/VolumeControl.cpp
===================================================================
--- haiku/trunk/src/bin/desklink/VolumeControl.cpp	2009-06-29 22:38:15 UTC (rev 31321)
+++ haiku/trunk/src/bin/desklink/VolumeControl.cpp	2009-06-30 10:14:54 UTC (rev 31322)
@@ -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(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 @@
 	if (archive->FindInt32("volume which", &volumeWhich) != B_OK)
 		volumeWhich = VOLUME_USE_MIXER;
 
-	_InitVolume(volumeWhich);
+	fMixerControl = new MixerControl(volumeWhich);
 }
 
 
@@ -109,10 +119,16 @@
 	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 @@
 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 @@
 				"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 @@
 
 
 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 @@
 		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 @@
 	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());
 }
 
 

Modified: haiku/trunk/src/bin/desklink/VolumeControl.h
===================================================================
--- haiku/trunk/src/bin/desklink/VolumeControl.h	2009-06-29 22:38:15 UTC (rev 31321)
+++ haiku/trunk/src/bin/desklink/VolumeControl.h	2009-06-30 10:14:54 UTC (rev 31322)
@@ -42,7 +42,8 @@
 	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 @@
 			bool			fSnapping;
 			float			fMinSnap;
 			float			fMaxSnap;
+
+			int32			fConnectRetries;
+			bool			fMediaServerRunning;
+			bool			fAddOnServerRunning;
 };
 
 #endif	// VOLUME_SLIDER_H




More information about the Haiku-commits mailing list