Merge pull request #2135 from michaelgregorius/alsa-combobox

Partial fix for #1600: ALSA device can be selected using a combo box
This commit is contained in:
Colin Wallace
2015-08-26 03:21:48 +00:00
21 changed files with 378 additions and 107 deletions

View File

@@ -22,6 +22,7 @@
*
*/
#include <QComboBox>
#include <QLineEdit>
#include <QLabel>
@@ -36,6 +37,8 @@
#include "gui_templates.h"
#include "templates.h"
#include <iostream>
#include <vector>
AudioAlsa::AudioAlsa( bool & _success_ful, Mixer* _mixer ) :
@@ -139,6 +142,59 @@ QString AudioAlsa::probeDevice()
/**
* @brief Creates a list of all available devices.
*
* Uses the hints API of ALSA to collect all devices. This also includes plug
* devices. The reason to collect these and not the raw hardware devices
* (e.g. hw:0,0) is that hardware devices often have a very limited number of
* supported formats, etc. Plugs on the other hand are software components that
* map all types of formats and inputs to the hardware and therefore they are
* much more flexible and more what we want.
*
* Further helpful info http://jan.newmarch.name/LinuxSound/Sampled/Alsa/.
*
* @return A collection of devices found on the system.
*/
AudioAlsa::DeviceInfoCollection AudioAlsa::getAvailableDevices()
{
DeviceInfoCollection deviceInfos;
char **hints;
/* Enumerate sound devices */
int err = snd_device_name_hint(-1, "pcm", (void***)&hints);
if (err != 0)
{
return deviceInfos;
}
char** n = hints;
while (*n != NULL)
{
char *name = snd_device_name_get_hint(*n, "NAME");
char *description = snd_device_name_get_hint(*n, "DESC");
if (name != 0 && description != 0)
{
deviceInfos.push_back(DeviceInfo(QString(name), QString(description)));
}
free(name);
free(description);
n++;
}
//Free the hint buffer
snd_device_name_free_hint((void**)hints);
return deviceInfos;
}
int AudioAlsa::handleError( int _err )
{
if( _err == -EPIPE )
@@ -491,52 +547,4 @@ int AudioAlsa::setSWParams()
return 0; // all ok
}
AudioAlsa::setupWidget::setupWidget( QWidget * _parent ) :
AudioDevice::setupWidget( AudioAlsa::name(), _parent )
{
m_device = new QLineEdit( AudioAlsa::probeDevice(), this );
m_device->setGeometry( 10, 20, 160, 20 );
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) );
dev_lbl->setGeometry( 10, 40, 160, 10 );
LcdSpinBoxModel * m = new LcdSpinBoxModel( /* this */ );
m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS );
m->setStep( 2 );
m->setValue( ConfigManager::inst()->value( "audioalsa",
"channels" ).toInt() );
m_channels = new LcdSpinBox( 1, this );
m_channels->setModel( m );
m_channels->setLabel( tr( "CHANNELS" ) );
m_channels->move( 180, 20 );
}
AudioAlsa::setupWidget::~setupWidget()
{
delete m_channels->model();
}
void AudioAlsa::setupWidget::saveSettings()
{
ConfigManager::inst()->setValue( "audioalsa", "device",
m_device->text() );
ConfigManager::inst()->setValue( "audioalsa", "channels",
QString::number( m_channels->value<int>() ) );
}
#endif

View File

@@ -425,7 +425,7 @@ void AudioJack::shutdownCallback( void * _udata )
AudioJack::setupWidget::setupWidget( QWidget * _parent ) :
AudioDevice::setupWidget( AudioJack::name(), _parent )
AudioDeviceSetupWidget( AudioJack::name(), _parent )
{
QString cn = ConfigManager::inst()->value( "audiojack", "clientname" );
if( cn.isEmpty() )

View File

@@ -329,7 +329,7 @@ void AudioOss::run()
AudioOss::setupWidget::setupWidget( QWidget * _parent ) :
AudioDevice::setupWidget( AudioOss::name(), _parent )
AudioDeviceSetupWidget( AudioOss::name(), _parent )
{
m_device = new QLineEdit( probeDevice(), this );
m_device->setGeometry( 10, 20, 160, 20 );

View File

@@ -389,7 +389,7 @@ void AudioPortAudioSetupUtil::updateChannels()
AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) :
AudioDevice::setupWidget( AudioPortAudio::name(), _parent )
AudioDeviceSetupWidget( AudioPortAudio::name(), _parent )
{
m_backend = new ComboBox( this, "BACKEND" );
m_backend->setGeometry( 64, 15, 260, 20 );

View File

@@ -280,7 +280,7 @@ void AudioPulseAudio::streamWriteCallback( pa_stream *s, size_t length )
AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) :
AudioDevice::setupWidget( AudioPulseAudio::name(), _parent )
AudioDeviceSetupWidget( AudioPulseAudio::name(), _parent )
{
m_device = new QLineEdit( AudioPulseAudio::probeDevice(), this );
m_device->setGeometry( 10, 20, 160, 20 );

View File

@@ -203,7 +203,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
AudioSdl::setupWidget::setupWidget( QWidget * _parent ) :
AudioDevice::setupWidget( AudioSdl::name(), _parent )
AudioDeviceSetupWidget( AudioSdl::name(), _parent )
{
QString dev = ConfigManager::inst()->value( "audiosdl", "device" );
m_device = new QLineEdit( dev, this );

View File

@@ -0,0 +1,122 @@
/*
* AudioAlsaSetupWidget.cpp - Implements a setup widget for ALSA-PCM-output
*
* Copyright (c) 2004-2015 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include <QComboBox>
#include <QLabel>
#include "AudioAlsaSetupWidget.h"
#ifdef LMMS_HAVE_ALSA
#include "ConfigManager.h"
#include "LcdSpinBox.h"
#include "gui_templates.h"
#include <iostream>
AudioAlsaSetupWidget::AudioAlsaSetupWidget( QWidget * _parent ) :
AudioDeviceSetupWidget( AudioAlsa::name(), _parent ),
m_selectedDevice(-1)
{
m_deviceInfos = AudioAlsa::getAvailableDevices();
QString deviceText = ConfigManager::inst()->value( "audioalsa", "device" );
m_deviceComboBox = new QComboBox(this);
for (size_t i = 0; i < m_deviceInfos.size(); ++i)
{
AudioAlsa::DeviceInfo const & currentDeviceInfo = m_deviceInfos[i];
QString comboBoxText = currentDeviceInfo.getDeviceName();
m_deviceComboBox->addItem(comboBoxText, QVariant(static_cast<uint>(i)));
QString toolTipText = currentDeviceInfo.getDeviceDescription();
m_deviceComboBox->setItemData(i, toolTipText, Qt::ToolTipRole);
if (currentDeviceInfo.getDeviceName() == deviceText)
{
m_deviceComboBox->setCurrentIndex(static_cast<int>(i));
}
}
m_selectedDevice = m_deviceComboBox->currentIndex();
m_deviceComboBox->setGeometry( 10, 20, 160, 20 );
connect(m_deviceComboBox,
SIGNAL(currentIndexChanged(int)),
SLOT(onCurrentIndexChanged(int)));
QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) );
dev_lbl->setGeometry( 10, 40, 160, 10 );
LcdSpinBoxModel * m = new LcdSpinBoxModel( /* this */ );
m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS );
m->setStep( 2 );
m->setValue( ConfigManager::inst()->value( "audioalsa",
"channels" ).toInt() );
m_channels = new LcdSpinBox( 1, this );
m_channels->setModel( m );
m_channels->setLabel( tr( "CHANNELS" ) );
m_channels->move( 180, 20 );
}
AudioAlsaSetupWidget::~AudioAlsaSetupWidget()
{
delete m_channels->model();
}
void AudioAlsaSetupWidget::saveSettings()
{
QString deviceText;
if (m_selectedDevice != -1)
{
AudioAlsa::DeviceInfo const & selectedDevice = m_deviceInfos[m_selectedDevice];
deviceText = selectedDevice.getDeviceName();
}
ConfigManager::inst()->setValue( "audioalsa", "device", deviceText );
ConfigManager::inst()->setValue( "audioalsa", "channels",
QString::number( m_channels->value<int>() ) );
}
void AudioAlsaSetupWidget::onCurrentIndexChanged(int index)
{
m_selectedDevice = index;
}
#endif

View File

@@ -0,0 +1,41 @@
/*
* AudioDeviceSetupWidget.cpp - Base class for audio device setup widgets
*
* Copyright (c) 2004-2015 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include "AudioDeviceSetupWidget.h"
AudioDeviceSetupWidget::AudioDeviceSetupWidget( const QString & _caption, QWidget * _parent ) :
TabWidget( TabWidget::tr( "Settings for %1" ).arg(TabWidget::tr( _caption.toLatin1() ) ).toUpper(),
_parent )
{
}
AudioDeviceSetupWidget::~AudioDeviceSetupWidget()
{
}
void AudioDeviceSetupWidget::show()
{
parentWidget()->show();
QWidget::show();
}

View File

@@ -2,6 +2,8 @@ SET(LMMS_SRCS
${LMMS_SRCS}
gui/AboutDialog.cpp
gui/ActionGroup.cpp
gui/AudioAlsaSetupWidget.cpp
gui/AudioDeviceSetupWidget.cpp
gui/AutomatableModelView.cpp
gui/AutomationPatternView.cpp
gui/ControllerConnectionDialog.cpp

View File

@@ -51,6 +51,7 @@
// platform-specific audio-interface-classes
#include "AudioAlsa.h"
#include "AudioAlsaSetupWidget.h"
#include "AudioJack.h"
#include "AudioOss.h"
#include "AudioPortAudio.h"
@@ -720,7 +721,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
#ifdef LMMS_HAVE_ALSA
m_audioIfaceSetupWidgets[AudioAlsa::name()] =
new AudioAlsa::setupWidget( asw );
new AudioAlsaSetupWidget( asw );
#endif
#ifdef LMMS_HAVE_PULSEAUDIO