lmms icon indicating copy to clipboard operation
lmms copied to clipboard

Improve PlayHandle removal in Mixer

Open M374LX opened this issue 5 years ago • 2 comments

Problem

In Mixer::renderNextBuffer(), when a clear signal is received (by calling Mixer::clear(), which sets m_clearSignal to true), Mixer::clearInternal() gets called and it simply adds every PlayHandle except InstrumentPlayHandles from m_playHandles to m_playHandlesToRemove. However, right after Mixer::clearInternal() is called in Mixer::renderNextBuffer(), a loop iterates through m_playHandlesToRemove and removes the same PlayHandles from m_playHandles. In other words, it unnecessarily stores a list of PlayHandles to be removed only to actually remove then right afterwards. Mixer::clear() seems to be called only within Song::stop().

Other than Mixer::clear(), the only method that adds a play handle to m_playHandlesToRemove is Mixer::removePlayHandle(), which is only called by the FileBrowser class to stop a preset preview PlayHandle. Also, only one preset preview PlayHandle seems to be active at a time.

Solution

  1. Add the members PresetPreviewPlayHandle m_presetPreviewPlayHandle and bool m_presetPreviewStopped to Mixer.

  2. Create the method Mixer::addPresetPreviewPlayHandle():

bool Mixer::addPresetPreviewPlayHandle( PresetPreviewPlayHandle *handle )
{
	m_presetPreviewStopped = false;
	m_presetPreviewPlayHandle = handle;
	return addPlayHandle( handle );
}
  1. Create the method Mixer::stopPresetPreview():
void Mixer::stopPreview()
{
	m_presetPreviewStopped = true;
}
  1. Modify Mixer::renderNextBuffer() so that:
if( m_clearSignal )
{
	m_clearSignal = false;
	clearInternal();
}

ConstPlayHandleList::Iterator it_rem = m_playHandlesToRemove.begin();
while( it_rem != m_playHandlesToRemove.end() )
{
	// [...]
}

becomes something like:

if( m_presetPreviewStopped && m_presetPreviewPlayHandle != NULL ) {
	//Actually stop m_presetPreviewPlayHandle [...]
	m_presetPreviewPlayHandle = NULL;
}

if( m_clearSignal )
{
	ConstPlayHandleList::Iterator it = m_playHandles.begin();
	while( it != m_playHandles.end() )
	{
		// [...]
	}

	m_clearSignal = false;
}
  1. Update FileBrowser.cpp with the new methods.

M374LX avatar Mar 03 '19 12:03 M374LX

Mixer::clearInternal was added in #2879 by @jasp00 to fix a deadlock. I think we can remove it once we find a solution without deadlocks. For preset previewing, I'm not sure why that can be an issue. I also think Mixer is not a place for handling preset previews.

PhysSong avatar Mar 08 '19 22:03 PhysSong

Mixer has been rewritten recently. Does this issue still occur?

Rossmaxx avatar Apr 14 '24 00:04 Rossmaxx