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