Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Server volume and mute after reboot #3125

Merged
merged 14 commits into from
Sep 3, 2017

Conversation

patrickdupuis
Copy link
Contributor

@patrickdupuis patrickdupuis commented Aug 11, 2017

This PR is an attempt to fix #3105 & #3110.

Description

The problem is that, on reboot, ServerTree calls its updateFunc (it was added the first time the server booted) before ServerBoot's initFunc is done sending the SynthDef. This causes the "SynthDef not found" error.

Changes proposed

The fix removes the updateFunc from ServerTree when the server quits. That way, on reboot, ServerTree has nothing to call. When initFunc is finished sending the SynthDef, updateFunc gets added to ServerTree.

Also, this.updateSynth needs to be called at the end of sendSynthDef so that the volume synth gets created, if necessary.

This change also makes Server.quit call Volume.freeSynth.

Result

The Server's volume and mute status persist across reboots. No more SynthDef not found errors posted after reboot.

Test

s.volume.volume = -36;
s.boot;
s.queryAllNodes;
/* should see this (if you have 2 outputs)
NODE TREE Group 0
   1 group
   1000 volumeAmpControl2
*/

s.quit;
s.boot;
s.queryAllNodes;
/* should see this (if you have 2 outputs)
NODE TREE Group 0
   1 group
   1000 volumeAmpControl2
*/
a = {SinOsc.ar}.play; // should play at -36db 
a.free;

s.mute;
s.quit;
s.boot;
a = {SinOsc.ar}.play; // no sound, server muted 
s.unmute; // should play at -36db
a.free;

s.quit;
s.options.numOutputBusChannels = 4;
s.boot;
s.queryAllNodes;
/* should see:
NODE TREE Group 0
   1 group
   1000 volumeAmpControl4
*/

@patrickdupuis
Copy link
Contributor Author

I messed up my first attempt at this PR. This is a redo.

@patrickdupuis
Copy link
Contributor Author

Oops... I should just stop now.

@patrickdupuis
Copy link
Contributor Author

Please review :)

@nhthn nhthn added the comp: class library SC class library label Aug 12, 2017
@nhthn nhthn added this to the 3.9 milestone Aug 12, 2017
@nhthn nhthn changed the base branch from master to 3.9 August 12, 2017 04:46
@nhthn nhthn self-assigned this Aug 12, 2017
@mossheim
Copy link
Contributor

would it be possible to add a regression test for this?

}).send(server);

server.sync;

this.updateSynth;

if(updateFunc.isNil) {
ServerTree.add(updateFunc = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while we're at it... this use of an assignment as an expression makes me cringe, could you move it out to updateFunc = { }; ServerTree.add(updateFunc)? i'm warming up to brian's policy of cleaning up adjacent code when working on things.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do!

Copy link
Contributor

@nhthn nhthn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can confirm that this fixes the issues. a unit test would be nice.

@telephon
Copy link
Member

please do go ahead and change that. I don't think an assignment in an argument should make you cringe, though. It can be a bit obscure. But it is a clear consequence of the fact that every expression returns a value.

but I'm fine with a change of course if it helps readability

@patrickdupuis
Copy link
Contributor Author

I can write a unit test for this in a few days.

@patrickdupuis
Copy link
Contributor Author

Hmmm... with my last commit I get a warning while booting. Everthing seems to work fine though.

SuperCollider 3 server ready.
JackDriver: max output latency 21.3 ms
WARNING: Server internal not running, could not send SynthDef.
Shared memory server interface initialized
Receiving notification messages from server 'localhost'

Looks like SynthDef.send complains that the server isn't running. I don't think this is caused by a mistake on my part. Rather, it's an issue that has become apparent with my last commit.

@patrickdupuis
Copy link
Contributor Author

I made the server sync before creating the SynthDef. Maybe this is a little too hacky? I'm open to improvements.


if(updateFunc.isNil) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't test it here, but could you make sure that ServerTree doesn't accumulate these functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any accumulation happening.

Copy link
Member

@telephon telephon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean that you start the server when you change the volume?

@patrickdupuis
Copy link
Contributor Author

No, you can change the volume and mute the server as usual. The server volume mechanism still functions as before, except for the missing SynthDef errors. What gives you the impression that the server will boot when the volume changes?

var server = Server.default;
var volume = Server.default.volume;
var level = Server.default.volume.volume;
var temp;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to me that a temp variable should not be declared at class scope, and probably deserves a better name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right. I'll fix that right away.

@patrickdupuis
Copy link
Contributor Author

patrickdupuis commented Sep 2, 2017

I've added a UnitTest to this PR. Please have a look.

In order to make the tests, I've had to modify Volume.sc slightly. Volume's ampSynth is now a getter. I've also made the local variable synthNumChans into a global variable called numOutputChannels. It's used in the SynthDef creation and can be used to get the number of channels of the ampSynth. I would have called it numChannels but that is already taken. To me, numOutputChannels is a better variable name. I can change it to synthNumChans if that's better..

Copy link
Member

@LFSaw LFSaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good. UnitTest is nice to have.

@@ -0,0 +1,40 @@
TestVolume : UnitTest {

var server = Server.default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this creates a parse error. Did you test the UnitTest?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started to look into this and got this far (see below). However, I got

PASS:a TestVolume:test_setVolume - initial volume is 0 db
*** ERROR: SynthDef volumeAmpControl2 not found
FAILURE IN SERVER /s_new SynthDef not found
PASS:a TestVolume:test_setVolume - Server volume synth exists
FAILURE IN SERVER /n_set Node 1000 not found
FAILURE IN SERVER /s_get Node 1000 not found
ERROR: Message '-' not understood.

now I need to sleep... so leave this to others...

TestVolume : UnitTest {

	test_setVolume {
		var server = Server.default;
		var serverVolume = server.volume.volume;
		var ampSynthVolume;

		this.bootServer;

		this.assert(serverVolume == 0, "initial volume is 0 db");

		server.volume.volume = -36;
		server.sync;
		this.assert(server.volume.ampSynth.notNil, "Server volume synth exists");

		server.volume.ampSynth.get(\volumeAmp, { |level| ampSynthVolume = level });
		server.sync;
		this.assertFloatEquals(ampSynthVolume, serverVolume, "volume level correctly set");

		server.volume.reset;
		server.sync;
		server.quit;
	}

// [...]
}

@patrickdupuis
Copy link
Contributor Author

@LFSaw thanks for looking at this. The tests should work now 👍

@LFSaw
Copy link
Member

LFSaw commented Sep 3, 2017

I confirmed with running the UnitTests locally.

@LFSaw LFSaw merged commit 79aa79f into supercollider:3.9 Sep 3, 2017
@mossheim
Copy link
Contributor

mossheim commented Sep 3, 2017

thanks for that @LFSaw :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
comp: class library SC class library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants