-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Partial fix for #1600: ALSA device can be selected using a combo box #2135
Conversation
Shows a combo box with the available ALSA cards and devices instead of a line edit. The problem currently is that the widgets are nested classes of AudioDevice and therefore the macro Q_OBJECT does not work which means that its not possible to define slots that react to retrieved signals.
Moved AudioDevice::setupWidget into its own class AudioDeviceSetupWidget which logically should belong to the GUI (unfortunately the include structure does not make this obvious). For the ALSA driver there is an implementation AudioAlsaSetupWidget which provides a combo box for selection of the card and device. All other driver widgets have been changed to inherit from AudioAlsaSetupWidget but have not been changed otherwise. SetupDialog has been adjusted to keep a map of AudioAlsaSetupWidgets now.
This version lets the user select the ALSA device to use with a combo box. It does not check whether the device works for the parameters that LMMS uses (SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_FORMAT_S16_LE, etc.). Doing these checks while compiling the list of available devices led to strange effects which are likely caused by the fact that the PCM device has to be opened to query its capabilities. This in turn led to error messages a la "Resource or device busy" when testing the new functionality repeatedly. However, having a combo box to select devices from should be a good step forward compared to a simple line edit. :)
void onCurrentIndexChanged(int index); | ||
|
||
private: | ||
QComboBox * m_deviceComboBox; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_deviceComboBox
is only accessed within the context in which it was created (AudioAlsaSetupWidget
's constructor), so could be made a local variable within the constructor instead of a member variable.
I don't know if this was intentional or not, as some people consider it a stylistic choice. Personally, I find extraneous member variables to be a bad thing. The more confined the scope of a variable, the fewer places you have to search through when debugging.
Hey @michaelgregorius, this is a fantastic idea and it fits right into the gui. I checked out your branch, and as you can probably also see with the Travis build logs, it fails:
The error appears to be this code: class AudioPortAudio : public AudioDevice
{
...
class setupWidget : public AudioDevice::setupWidget
{
...
} Namely, you forgot to fix the parent class from Besides that though, I reviewed the code fairly thoroughly, primarily looking for possible memory errors, and it looked OK. It may be worth separating the implementation from the header in your new I also left a few inline comments for you. Great work though! Looking forward to integrating this into master, although I suspect it will have to wait until after 1.2 due to feature freeze :/ |
Removal of a superfluous include in AudioAlsaSetupWidget.cpp Removal of the function "bool hasCapabilities(char *device_name)" which was not used anyway. It implemented a test for ALSA device capabilities needed by LMMS (SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_FORMAT_S16_LE, etc.). Corrected header name in AudioAlsaSetupWidget.h. Created an implementation file for AudioDeviceSetupWidget to make more clear that it's part of the GUI. Fix build for builds that use Port Audio. The setup widget of AudioPortAudio.h still inherited from AudioDevice::setupWidget instead of the new AudioDeviceSetupWidget.
Hi @Wallacoloo! Thanks for the really thorough code review and the nice words! I have pushed a new commit that fixes everything except the member Hope that the Travis build goes through now as I had to fix it blindly because I do not build with PortAudio. |
@michaelgregorius Great! I gave it a test, and it seems to work well enough for me ("default", "pulse" and "sysdefault" all produce the same output. "null" produces silence, as expected. The other ones shown produce silence and also cause for LMMS to show the audio device settings dialog upon restart, which I believe indicates a failure to open the device). I believe this is the expected behavior, until it gets refined by fixing up the I also tested setting the device to "bogus" in master and then opened your alsa-combobox branch, and it seemed to handle things pretty well by automatically setting the ALSA device to "default". If I gave it something valid like "pulse", on the other hand, it preserved the device setting. So users shouldn't experience any upgrade problems 👍 |
By the way, the LMMS PortAudio backend appears to be capable of narrowing down the compatible ALSA devices before selection. Their code may be of reference for getting |
|
||
free(name); | ||
free(description); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move those two 'free' calls inside above 'if' statement. If 'name' or 'description' are NULL, we have a crash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Nice catch!
However I would have tested against NULL or nullptr instead of 0 but this is pure personal taste :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember seeing this earlier & looking into it. Turns out it's perfectly valid to free a null pointer in C/C++: http://www.cplusplus.com/reference/cstdlib/free/
Additionally, moving BOTH calls to free
into the if statement would cause a memory leak in the case that only one of them is null. So I vote to leave as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that was the intention. That's also the reason why sometimes you can see code like this:
delete m_pointer;
m_pointer = 0;
It's ok to call delete
on a null pointer but not ok to delete the same pointer (address) twice. By setting it to 0
after the deletion you make sure that you will only run into the valid case in case the code is called again without allocating something new for m_pointer
.
Somehow I forgot about this PR, with everything else going on. Sorry for that. I retested this after locally rebasing it against master, and it's still working great. So, merge time! |
Partial fix for #1600: ALSA device can be selected using a combo box
👍 Although next time we should consider a rebase first. :) |
Implements the selection of ALSA devices using a combo box as proposed by @unfa in #1600. The ALSA configuration dialog looks as follows in this branch:
Please note that the current implementation does not check whether the device works for the parameters that LMMS uses (
SND_PCM_ACCESS_RW_INTERLEAVED
,SND_PCM_FORMAT_S16_LE
, etc.). I tried doing these checks while compiling the list of available devices but this led to strange effects which are likely caused by the fact that the PCM device has to be opened to query its capabilities. After testing the selection repeatedly I got error messages a la "Resource or device busy".However, having a combo box to select devices from should be a good step forward compared to a simple line edit. 😃
To be able to react to combo box selection changes several changes were necessary.
AudioDevice::setupWidget
was moved into its own classAudioDeviceSetupWidget
which logically should belong to the GUI (unfortunately the include structure does not make this obvious). This was needed so that inheriting classes can use theQ_OBJECT
macro, e.g. to connect signals and slots.For the ALSA driver there is an implementation
AudioAlsaSetupWidget
which provides a combo box for selection of the device. The available devices are pulled from a static method in theAudioAlsa
class.All other driver widgets have been changed to inherit from
AudioDeviceSetupWidget
but have not been changed otherwise.SetupDialog has been adjusted to keep a map of
AudioDeviceSetupWidgets
now.