From 79cae31b5bfe0c6615b0cb645347b0ed90b4d680 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 26 Jun 2015 17:14:47 +0200 Subject: [PATCH] Some refactoring to enable signals in audio driver setup dialogs 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. --- include/AudioAlsa.h | 25 --- include/AudioAlsaSetupWidget.h | 103 ++++++++++ include/AudioDevice.h | 26 --- include/AudioDeviceSetupWidget.h | 55 ++++++ include/AudioDummy.h | 5 +- include/AudioJack.h | 3 +- include/AudioOss.h | 3 +- include/AudioPulseAudio.h | 3 +- include/AudioSdl.h | 3 +- include/SetupDialog.h | 4 +- src/core/audio/AudioAlsa.cpp | 294 ----------------------------- src/core/audio/AudioJack.cpp | 2 +- src/core/audio/AudioOss.cpp | 2 +- src/core/audio/AudioPulseAudio.cpp | 2 +- src/core/audio/AudioSdl.cpp | 2 +- src/gui/AudioAlsaSetupWidget.cpp | 267 ++++++++++++++++++++++++++ src/gui/CMakeLists.txt | 1 + src/gui/SetupDialog.cpp | 3 +- 18 files changed, 446 insertions(+), 357 deletions(-) create mode 100644 include/AudioAlsaSetupWidget.h create mode 100644 include/AudioDeviceSetupWidget.h create mode 100644 src/gui/AudioAlsaSetupWidget.cpp diff --git a/include/AudioAlsa.h b/include/AudioAlsa.h index 4043aafd5..a916ad8da 100644 --- a/include/AudioAlsa.h +++ b/include/AudioAlsa.h @@ -37,11 +37,6 @@ #include "AudioDevice.h" -class QComboBox; -class LcdSpinBox; -class QLineEdit; - - class AudioAlsa : public AudioDevice, public QThread { public: @@ -56,26 +51,6 @@ public: static QString probeDevice(); - - class setupWidget : public AudioDevice::setupWidget - { - public: - setupWidget( QWidget * _parent ); - virtual ~setupWidget(); - - virtual void saveSettings(); - - public slots: - void onCurrentIndexChanged(int index); - - private: - QComboBox * m_deviceComboBox; - QLineEdit * m_device; - LcdSpinBox * m_channels; - - } ; - - private: virtual void startProcessing(); virtual void stopProcessing(); diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h new file mode 100644 index 000000000..0e2f9b69c --- /dev/null +++ b/include/AudioAlsaSetupWidget.h @@ -0,0 +1,103 @@ +/* + * AudioAlsa.h - device-class that implements ALSA-PCM-output + * + * Copyright (c) 2004-2009 Tobias Doerffel + * + * 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. + * + */ + +#ifndef AUDIO_ALSA_SETUP_WIDGET_H +#define AUDIO_ALSA_SETUP_WIDGET_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_ALSA + +#include "AudioDeviceSetupWidget.h" + +#include + + +class QComboBox; +class LcdSpinBox; +class QLineEdit; + + +class AudioAlsaSetupWidget : public AudioDeviceSetupWidget +{ + Q_OBJECT + +public: + AudioAlsaSetupWidget( QWidget * _parent ); + virtual ~AudioAlsaSetupWidget(); + + virtual void saveSettings(); + +public slots: + void onCurrentIndexChanged(int index); + +private: + class DeviceInfo + { + public: + DeviceInfo(int cardNumber, int deviceNumber, + QString const & cardName, QString const & pcmName, + QString const & cardId, QString const & pcmId) : + m_cardNumber(cardNumber), + m_deviceNumber(deviceNumber), + m_cardName(cardName), + m_pcmName(pcmName), + m_cardId(cardId), + m_pcmId(pcmId) + {} + ~DeviceInfo() {} + + int getCardNumber() const { return m_cardNumber; } + int getDeviceNumber() const { return m_deviceNumber; } + QString const & getCardName() const { return m_cardName; } + QString const & getPcmName() const { return m_pcmName; } + QString const & getCardId() const { return m_cardId; } + QString const & getPcmId() const { return m_pcmId; } + + QString getHWString() const { return QString("hw:%1,%2").arg(m_cardNumber).arg(m_deviceNumber); } + + private: + int m_cardNumber; + int m_deviceNumber; + QString m_cardName; + QString m_pcmName; + QString m_cardId; + QString m_pcmId; + }; + + void populateDeviceInfos(std::vector &deviceInfos); + +private: + QComboBox * m_deviceComboBox; + QLineEdit * m_device; + LcdSpinBox * m_channels; + + int m_selectedDevice; + typedef std::vector DeviceInfoCollection; + DeviceInfoCollection m_deviceInfos; +} ; + +#endif + +#endif diff --git a/include/AudioDevice.h b/include/AudioDevice.h index 298279ddb..0782035b7 100644 --- a/include/AudioDevice.h +++ b/include/AudioDevice.h @@ -90,32 +90,6 @@ public: - class setupWidget : public TabWidget - { - public: - setupWidget( const QString & _caption, QWidget * _parent ) : - TabWidget( TabWidget::tr( "Settings for %1" ).arg( - TabWidget::tr( _caption.toLatin1() ) ). - toUpper(), _parent ) - { - } - - virtual ~setupWidget() - { - } - - virtual void saveSettings() = 0; - - virtual void show() - { - parentWidget()->show(); - QWidget::show(); - } - - } ; - - - protected: // subclasses can re-implement this for being used in conjunction with // processNextBuffer() diff --git a/include/AudioDeviceSetupWidget.h b/include/AudioDeviceSetupWidget.h new file mode 100644 index 000000000..95eeaed88 --- /dev/null +++ b/include/AudioDeviceSetupWidget.h @@ -0,0 +1,55 @@ +/* + * AudioDevice.h - base-class for audio-devices, used by LMMS-mixer + * + * Copyright (c) 2004-2014 Tobias Doerffel + * + * 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. + * + */ + +#ifndef AUDIO_DEVICE_SETUP_WIDGET_H +#define AUDIO_DEVICE_SETUP_WIDGET_H + +#include "TabWidget.h" + + +class AudioDeviceSetupWidget : public TabWidget +{ +public: + AudioDeviceSetupWidget( const QString & _caption, QWidget * _parent ) : + TabWidget( TabWidget::tr( "Settings for %1" ).arg( + TabWidget::tr( _caption.toLatin1() ) ). + toUpper(), _parent ) + { + } + + virtual ~AudioDeviceSetupWidget() + { + } + + virtual void saveSettings() = 0; + + virtual void show() + { + parentWidget()->show(); + QWidget::show(); + } +}; + + +#endif diff --git a/include/AudioDummy.h b/include/AudioDummy.h index 31781e049..993dbccae 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -26,6 +26,7 @@ #define AUDIO_DUMMY_H #include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" #include "MicroTimer.h" @@ -49,11 +50,11 @@ public: } - class setupWidget : public AudioDevice::setupWidget + class setupWidget : public AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ) : - AudioDevice::setupWidget( AudioDummy::name(), _parent ) + AudioDeviceSetupWidget( AudioDummy::name(), _parent ) { } diff --git a/include/AudioJack.h b/include/AudioJack.h index 35801ef03..ec4fc5819 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -35,6 +35,7 @@ #include #include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" class QLineEdit; @@ -55,7 +56,7 @@ public: } - class setupWidget : public AudioDevice::setupWidget + class setupWidget : public AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioOss.h b/include/AudioOss.h index b40edd58e..76dbeecb8 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -30,6 +30,7 @@ #ifdef LMMS_HAVE_OSS #include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" class LcdSpinBox; @@ -50,7 +51,7 @@ public: static QString probeDevice(); - class setupWidget : public AudioDevice::setupWidget + class setupWidget : public AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index 5a8504d1f..fc2f77bd4 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -32,6 +32,7 @@ #include #include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" class LcdSpinBox; @@ -52,7 +53,7 @@ public: static QString probeDevice(); - class setupWidget : public AudioDevice::setupWidget + class setupWidget : public AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioSdl.h b/include/AudioSdl.h index 15facb52a..ba2f09faa 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -33,6 +33,7 @@ #include #include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" class QLineEdit; @@ -50,7 +51,7 @@ public: } - class setupWidget : public AudioDevice::setupWidget + class setupWidget : public AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 3357bf54c..d5e1b6e57 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -33,6 +33,8 @@ #include "AudioDevice.h" #include "MidiClient.h" +#include "AudioDeviceSetupWidget.h" + class QComboBox; class QLabel; @@ -178,7 +180,7 @@ private: bool m_displayWaveform; bool m_disableAutoQuit; - typedef QMap AswMap; + typedef QMap AswMap; typedef QMap MswMap; typedef QMap trMap; diff --git a/src/core/audio/AudioAlsa.cpp b/src/core/audio/AudioAlsa.cpp index 8438b5177..830effe2b 100644 --- a/src/core/audio/AudioAlsa.cpp +++ b/src/core/audio/AudioAlsa.cpp @@ -494,298 +494,4 @@ int AudioAlsa::setSWParams() return 0; // all ok } - - -void testPrintCards() -{ - std::cout << "Listing cards: " << std::endl; - char **hints; - - /* Enumerate sound devices */ - int err = snd_device_name_hint(-1, "pcm", (void***)&hints); - if (err != 0) - return;//Error! Just return - - char** n = hints; - while (*n != NULL) { - - char *name = snd_device_name_get_hint(*n, "NAME"); - - if (name != NULL && 0 != strcmp("null", name)) { - //Copy name to another buffer and then free it - std::cout << "Name: " << name << std::endl; - - free(name); - } - - char *description = snd_device_name_get_hint(*n, "DESC"); - - if (description != NULL && 0 != strcmp("null", name)) { - //Copy name to another buffer and then free it - std::cout << "Description: " << description << std::endl; - - free(description); - } - else - { - std::cout << "No description" << std::endl; - } - - std::cout << std::endl; - - n++; - }//End of while - - //Free hint buffer too - snd_device_name_free_hint((void**)hints); -} - - - -void device_list(void) -{ - snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; - snd_ctl_t *handle; - int card, err, dev, idx; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - - card = -1; - if (snd_card_next(&card) < 0 || card < 0) { - return; - } - std::cout << "**** List of " << snd_pcm_stream_name(stream) << " Hardware Devices ****\n"; - - while (card >= 0) { - char name[32]; - sprintf(name, "hw:%d", card); - if ((err = snd_ctl_open(&handle, name, 0)) < 0) { - // TODO Error handling - //error("control open (%i): %s", card, snd_strerror(err)); - goto next_card; - } - if ((err = snd_ctl_card_info(handle, info)) < 0) { - // TODO Error handling - //error("control hardware info (%i): %s", card, snd_strerror(err)); - snd_ctl_close(handle); - goto next_card; - } - dev = -1; - while (1) { - unsigned int count; - if (snd_ctl_pcm_next_device(handle, &dev)<0) - // TODO Error handling - //error("snd_ctl_pcm_next_device"); - std::cerr << "snd_ctl_pcm_next_device"; - if (dev < 0) - break; - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { - if (err != -ENOENT) - // TODO Error handling - //error("control digital audio info (%i): %s", card, snd_strerror(err)); - std::cerr << "Error\n"; - continue; - } - //std::cout << "card " << card << ": " << snd_ctl_card_info_get_id(info) << " [" << snd_ctl_card_info_get_name(info) << "], device " << dev << - // ": " << snd_pcm_info_get_id(pcminfo) << " [" << snd_pcm_info_get_name(pcminfo) << "]\n"; - std::cout << "card hw" << card << ":" << dev << " - " << "[" << snd_ctl_card_info_get_name(info) << "/" << snd_pcm_info_get_name(pcminfo) << "], " << - snd_ctl_card_info_get_id(info) << "," << snd_pcm_info_get_id(pcminfo) << "\n"; - - count = snd_pcm_info_get_subdevices_count(pcminfo); - std::cout << " Subdevices: " << snd_pcm_info_get_subdevices_avail(pcminfo) << "/" << count << std::endl; - for (idx = 0; idx < (int)count; idx++) { - snd_pcm_info_set_subdevice(pcminfo, idx); - if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { - // TODO Error handling - //error("control digital audio playback info (%i): %s", card, snd_strerror(err)); - std::cerr << "Error\n"; - } else { - std::cout << " Subdevice #" << idx << ": " << snd_pcm_info_get_subdevice_name(pcminfo) << std::endl; - } - } - } - snd_ctl_close(handle); -next_card: - if (snd_card_next(&card) < 0) { - // TODO Error handling - //error("snd_card_next"); - break; - } - } -} - - - -class DeviceInfo -{ -public: - DeviceInfo(int cardNumber, int deviceNumber, - QString const & cardName, QString const & pcmName, - QString const & cardId, QString const & pcmId) : - m_cardNumber(cardNumber), - m_deviceNumber(deviceNumber), - m_cardName(cardName), - m_pcmName(pcmName), - m_cardId(cardId), - m_pcmId(pcmId) - {} - ~DeviceInfo() {} - - int getCardNumber() const { return m_cardNumber; } - int getDeviceNumber() const { return m_deviceNumber; } - QString const & getCardName() const { return m_cardName; } - QString const & getPcmName() const { return m_pcmName; } - QString const & getCardId() const { return m_cardId; } - QString const & getPcmId() const { return m_pcmId; } - - QString getHWString() const { return QString("hw%1:%2").arg(m_cardNumber).arg(m_deviceNumber); } - -private: - int m_cardNumber; - int m_deviceNumber; - QString m_cardName; - QString m_pcmName; - QString m_cardId; - QString m_pcmId; -}; - - - -void populateDeviceInfos(std::vector &deviceInfos) -{ - snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; - snd_ctl_t *handle; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - - // Allocate memory for the info structs - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - - int card = -1; - - while (!snd_card_next(&card) && card >= 0) - { - std::cout << "Card: " << card << " found!" << std::endl; - - char name[32]; - sprintf(name, "hw:%d", card); - - if (snd_ctl_open(&handle, name, 0) < 0) - { - std::cerr << "Error opening ALSA card " << name << std::endl; - continue; - } - if (snd_ctl_card_info(handle, info) < 0) - { - snd_ctl_close(handle); - std::cerr << "Could not retrieve info for ALSA card " << name << std::endl; - continue; - } - - int dev = -1; - - while (!snd_ctl_pcm_next_device(handle, &dev) && dev >= 0) - { - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - if (!snd_ctl_pcm_info(handle, pcminfo)) - { - QString cardName(snd_ctl_card_info_get_name(info)); - QString pcmName(snd_pcm_info_get_name(pcminfo)); - QString cardId(snd_ctl_card_info_get_id(info)); - QString pcmId(snd_pcm_info_get_id(pcminfo)); - - DeviceInfo currentDevice(card, dev, cardName, pcmName, cardId, pcmId); - deviceInfos.push_back(currentDevice); - - std::cout << "card hw" << card << ":" << dev << " - " << "[" << snd_ctl_card_info_get_name(info) << "/" << snd_pcm_info_get_name(pcminfo) << "], " << - snd_ctl_card_info_get_id(info) << "," << snd_pcm_info_get_id(pcminfo) << std::endl; - } - } - - snd_ctl_close(handle); - } -} - - - - -AudioAlsa::setupWidget::setupWidget( QWidget * _parent ) : - AudioDevice::setupWidget( AudioAlsa::name(), _parent ) -{ - typedef std::vector DeviceInfoCollection; - DeviceInfoCollection deviceInfos; - populateDeviceInfos(deviceInfos); - - // Implements the "-l" from aplay - //device_list(); - - //testPrintCards(); - - m_deviceComboBox = new QComboBox(this); - for (size_t i = 0; i < deviceInfos.size(); ++i) - { - DeviceInfo const & currentDeviceInfo = deviceInfos[i]; - QString comboBoxText = currentDeviceInfo.getHWString() + " [" + currentDeviceInfo.getCardName() + " | " + currentDeviceInfo.getPcmName() + "]"; - m_deviceComboBox->addItem(comboBoxText, QVariant(static_cast(i))); - m_deviceComboBox->setItemData(i, comboBoxText, Qt::ToolTipRole); - } - - m_deviceComboBox->setGeometry( 10, 20, 160, 20 ); - connect(m_deviceComboBox, SIGNAL(currentIndexChanged(int)), SLOT(onCurrentIndexChanged(int))); - - //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() ) ); -} - - - -void AudioAlsa::setupWidget::onCurrentIndexChanged(int index) -{ - -} - - #endif diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index b491ea826..137c5b445 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -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() ) diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index f280da0f9..4a92b3cf5 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -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 ); diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index a1d1e740f..4463bab8a 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -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 ); diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index 6285b4d4b..4587a61f3 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -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 ); diff --git a/src/gui/AudioAlsaSetupWidget.cpp b/src/gui/AudioAlsaSetupWidget.cpp new file mode 100644 index 000000000..7f74bcecf --- /dev/null +++ b/src/gui/AudioAlsaSetupWidget.cpp @@ -0,0 +1,267 @@ +/* + * AudioAlsa.cpp - device-class which implements ALSA-PCM-output + * + * Copyright (c) 2004-2014 Tobias Doerffel + * + * 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 +#include +#include + +#include "AudioAlsa.h" +#include "AudioAlsaSetupWidget.h" + +#ifdef LMMS_HAVE_ALSA + +#include "ConfigManager.h" +#include "LcdSpinBox.h" +#include "gui_templates.h" + +#include + + +void device_list(void) +{ + snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; + snd_ctl_t *handle; + int card, err, dev, idx; + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo); + + card = -1; + if (snd_card_next(&card) < 0 || card < 0) { + return; + } + std::cout << "**** List of " << snd_pcm_stream_name(stream) << " Hardware Devices ****\n"; + + while (card >= 0) { + char name[32]; + sprintf(name, "hw:%d", card); + if ((err = snd_ctl_open(&handle, name, 0)) < 0) { + // TODO Error handling + //error("control open (%i): %s", card, snd_strerror(err)); + goto next_card; + } + if ((err = snd_ctl_card_info(handle, info)) < 0) { + // TODO Error handling + //error("control hardware info (%i): %s", card, snd_strerror(err)); + snd_ctl_close(handle); + goto next_card; + } + dev = -1; + while (1) { + unsigned int count; + if (snd_ctl_pcm_next_device(handle, &dev)<0) + // TODO Error handling + //error("snd_ctl_pcm_next_device"); + std::cerr << "snd_ctl_pcm_next_device"; + if (dev < 0) + break; + snd_pcm_info_set_device(pcminfo, dev); + snd_pcm_info_set_subdevice(pcminfo, 0); + snd_pcm_info_set_stream(pcminfo, stream); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { + if (err != -ENOENT) + // TODO Error handling + //error("control digital audio info (%i): %s", card, snd_strerror(err)); + std::cerr << "Error\n"; + continue; + } + //std::cout << "card " << card << ": " << snd_ctl_card_info_get_id(info) << " [" << snd_ctl_card_info_get_name(info) << "], device " << dev << + // ": " << snd_pcm_info_get_id(pcminfo) << " [" << snd_pcm_info_get_name(pcminfo) << "]\n"; + std::cout << "card hw" << card << ":" << dev << " - " << "[" << snd_ctl_card_info_get_name(info) << "/" << snd_pcm_info_get_name(pcminfo) << "], " << + snd_ctl_card_info_get_id(info) << "," << snd_pcm_info_get_id(pcminfo) << "\n"; + + count = snd_pcm_info_get_subdevices_count(pcminfo); + std::cout << " Subdevices: " << snd_pcm_info_get_subdevices_avail(pcminfo) << "/" << count << std::endl; + for (idx = 0; idx < (int)count; idx++) { + snd_pcm_info_set_subdevice(pcminfo, idx); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { + // TODO Error handling + //error("control digital audio playback info (%i): %s", card, snd_strerror(err)); + std::cerr << "Error\n"; + } else { + std::cout << " Subdevice #" << idx << ": " << snd_pcm_info_get_subdevice_name(pcminfo) << std::endl; + } + } + } + snd_ctl_close(handle); +next_card: + if (snd_card_next(&card) < 0) { + // TODO Error handling + //error("snd_card_next"); + break; + } + } +} + + + +void AudioAlsaSetupWidget::populateDeviceInfos(std::vector &deviceInfos) +{ + snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; + snd_ctl_t *handle; + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + + // Allocate memory for the info structs + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo); + + int card = -1; + + while (!snd_card_next(&card) && card >= 0) + { + std::cout << "Card: " << card << " found!" << std::endl; + + char name[32]; + sprintf(name, "hw:%d", card); + + if (snd_ctl_open(&handle, name, 0) < 0) + { + std::cerr << "Error opening ALSA card " << name << std::endl; + continue; + } + if (snd_ctl_card_info(handle, info) < 0) + { + snd_ctl_close(handle); + std::cerr << "Could not retrieve info for ALSA card " << name << std::endl; + continue; + } + + int dev = -1; + + while (!snd_ctl_pcm_next_device(handle, &dev) && dev >= 0) + { + snd_pcm_info_set_device(pcminfo, dev); + snd_pcm_info_set_subdevice(pcminfo, 0); + snd_pcm_info_set_stream(pcminfo, stream); + if (!snd_ctl_pcm_info(handle, pcminfo)) + { + QString cardName(snd_ctl_card_info_get_name(info)); + QString pcmName(snd_pcm_info_get_name(pcminfo)); + QString cardId(snd_ctl_card_info_get_id(info)); + QString pcmId(snd_pcm_info_get_id(pcminfo)); + + DeviceInfo currentDevice(card, dev, cardName, pcmName, cardId, pcmId); + deviceInfos.push_back(currentDevice); + + std::cout << "card hw" << card << ":" << dev << " - " << "[" << snd_ctl_card_info_get_name(info) << "/" << snd_pcm_info_get_name(pcminfo) << "], " << + snd_ctl_card_info_get_id(info) << "," << snd_pcm_info_get_id(pcminfo) << std::endl; + } + } + + snd_ctl_close(handle); + } +} + + + + +AudioAlsaSetupWidget::AudioAlsaSetupWidget( QWidget * _parent ) : + AudioDeviceSetupWidget( AudioAlsa::name(), _parent ), + m_selectedDevice(-1) +{ + populateDeviceInfos(m_deviceInfos); + + QString deviceText = ConfigManager::inst()->value( "audioalsa", "device" ); + + // Implements the "-l" from aplay + //device_list(); + + m_deviceComboBox = new QComboBox(this); + for (size_t i = 0; i < m_deviceInfos.size(); ++i) + { + DeviceInfo const & currentDeviceInfo = m_deviceInfos[i]; + QString comboBoxText = currentDeviceInfo.getHWString() + " [" + currentDeviceInfo.getCardName() + " | " + currentDeviceInfo.getPcmName() + "]"; + m_deviceComboBox->addItem(comboBoxText, QVariant(static_cast(i))); + m_deviceComboBox->setItemData(i, comboBoxText, Qt::ToolTipRole); + + if (currentDeviceInfo.getHWString() == deviceText) + { + m_deviceComboBox->setCurrentIndex(static_cast(i)); + } + } + + m_selectedDevice = m_deviceComboBox->currentIndex(); + + m_deviceComboBox->setGeometry( 10, 20, 160, 20 ); + connect(m_deviceComboBox, + SIGNAL(currentIndexChanged(int)), + SLOT(onCurrentIndexChanged(int))); + + //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 ); + +} + + + + +AudioAlsaSetupWidget::~AudioAlsaSetupWidget() +{ + delete m_channels->model(); +} + + + + +void AudioAlsaSetupWidget::saveSettings() +{ + QString deviceText; + + if (m_selectedDevice != -1) + { + DeviceInfo const & selectedDevice = m_deviceInfos[m_selectedDevice]; + deviceText = selectedDevice.getHWString(); + } + + ConfigManager::inst()->setValue( "audioalsa", "device", deviceText ); + ConfigManager::inst()->setValue( "audioalsa", "channels", + QString::number( m_channels->value() ) ); +} + + + +void AudioAlsaSetupWidget::onCurrentIndexChanged(int index) +{ + m_selectedDevice = index; +} + + +#endif diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index a23c37f81..bfe43f15c 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -2,6 +2,7 @@ SET(LMMS_SRCS ${LMMS_SRCS} gui/AboutDialog.cpp gui/ActionGroup.cpp + gui/AudioAlsaSetupWidget.cpp gui/AutomatableModelView.cpp gui/AutomationPatternView.cpp gui/ControllerConnectionDialog.cpp diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 7ca9911ce..fd6233df8 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -51,6 +51,7 @@ // platform-specific audio-interface-classes #include "AudioAlsa.h" +#include "AudioAlsaSetupWidget.h" #include "AudioJack.h" #include "AudioOss.h" #include "AudioPortAudio.h" @@ -719,7 +720,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