beep icon indicating copy to clipboard operation
beep copied to clipboard

Method for closing the context and hence releasing the device

Open avivklas opened this issue 6 years ago • 9 comments
trafficstars

The audio device never releases after calling speaker.Init() I suggest to extract the following code from Init():

if player != nil {
	done <- struct{}{}
	player.Close()
	context.Close()
}

to a separated public method.

What do you think?

BTW, great work! This pkg is the cornerstone of a project I'm working on

avivklas avatar May 14 '19 15:05 avivklas

Hi! Thanks for the suggestion! The usefulness of this suggestion depends on whether it is actually necessary to close the device before the program exits.

I'm not sure about that, but I'll try and research when I get home. If you research first, that would help too :)

And I'm glad you find this package useful :). Btw, don't call speaker.Init every time you play something. It's likely that you don't do it, I just see so much of it on GitHub that I decided to tell whoever I can :D

faiface avatar May 14 '19 15:05 faiface

Hi Michal,

I've got this idea because my app runs on the same machine along with a Spotify client and after calling speaker.Init(), the device get locked for my process and never releases even after stream ends. It's only when I close the process that Spotify is able to use the device again. So I've searched the code for the cause and I've figured that only when calling `context.close()', the driver (alsa in my case) releases the sound device.

But if only speaker.Init() opens the context again and one should not call it multiple times than maybe speaker.Play() should assert that context is opened instead of speaker.Init() and I still need speaker.Close() or something like that to release the device by calling context.Close() I hope that I talk sense. Otherwise, please guide me through to a solution and I'll do whatever needed. I'll share my still pre-mature project soon, btw.

Thanks!

avivklas avatar May 14 '19 17:05 avivklas

Hm, that's pretty interesting. Beep uses Oto for accessing audio hardware and I made the ALSA driver for it, so I'm familiar with it :D. The ALSA driver asks for the "default" device, which should mean that it gets supplied a virtual device that gets mixed with the sounds from all other applications. In other words: it shouldn't block audio from other apps.

I'm still not home, so I can't test whether that actually works, but I'll do that ASAP when I get there.

But other than that, yeah, this function would probably have its uses in some specific settings. Would you be up for adding it yourself in a PR? ;)

faiface avatar May 14 '19 18:05 faiface

Sure. With pleasure.

Although you are probably right about my usage of alsa device on the machine.

avivklas avatar May 14 '19 18:05 avivklas

Thanks! Make sure to document it that it's not necessary to call the function at all, it's there just for the special purposes of releasing a device if your system doesn't do proper mixing.

faiface avatar May 14 '19 18:05 faiface

👍

avivklas avatar May 14 '19 18:05 avivklas

@faiface @avivklas I can confirm that I am seeing the same audio channel blocking issue on Linux (Linux 5.3.0-7648-generic).

Here's an example where I'm using fuser to determine user-space processes using /dev/snd/* and I'm running Spotify

                              USER        PID ACCESS COMMAND
/dev/snd/controlC0:  yelkalay   2321 F.... pulseaudio
/dev/snd/controlC1:  yelkalay   2321 F.... pulseaudio
/dev/snd/pcmC0D0p:   yelkalay   2321 F...m pulseaudio

F in the third line refer to the device being open for writing and m a memory mapped file/shared lib.

When I run my Beep/Go binary called soundmachine I get the following:

                    USER        PID ACCESS COMMAND
/dev/snd/controlC0:  yelkalay   2321 F.... pulseaudio
                     yelkalay   8960 F.... soundmachine
/dev/snd/controlC1:  yelkalay   2321 F.... pulseaudio
/dev/snd/pcmC0D0p:   yelkalay   8960 F...m soundmachine
/dev/snd/timer:      yelkalay   8960 f.... soundmachine

Should Beep/Oto be keeping /dev/snd/timer open? The f access state on the last line of that previous example refers to an "open" file - which presumably is blocked from being used by any other process. A post in the ALSA mailing list states that in general userspace applications shouldn't be doing anything to /dev/snd/timer

Haven't had time to dig through code to see why this happening but perhaps this can clue both of you into why this is happening.

buildscientist avatar Jul 10 '20 01:07 buildscientist

Looks like @avivklas added speaker.Close() in 641d0bf5c48b1888225b21de45d612399f05e17b which resolves this issue.

Any chance we can add another tutorial to the Wiki briefly going over why this is an issue and how to get around it?

In this case every time I call speaker.Close() I'll need to reinitialize the player via speaker.Init()

buildscientist avatar Jul 10 '20 06:07 buildscientist

This issue is somewhat related to https://github.com/hajimehoshi/oto/issues/54

buildscientist avatar Jul 10 '20 06:07 buildscientist