2019-08-24 Fred Gleason <fredg@paravelsystems.com>

* Refactored rdalsaconfig(8) to use ALSA device IDs rather than
	ordinal numbers in asound.confO(5).
This commit is contained in:
Fred Gleason 2019-08-24 09:16:18 -04:00
parent e62b02f179
commit f6d220c56c
12 changed files with 541 additions and 548 deletions

View File

@ -18947,3 +18947,6 @@
the target event was unplayable.
2019-08-21 Fred Gleason <fredg@paravelsystems.com>
* Re-indented switch() statements in 'lib/rdlogplay.cpp'.
2019-08-24 Fred Gleason <fredg@paravelsystems.com>
* Refactored rdalsaconfig(8) to use ALSA device IDs rather than
ordinal numbers in asound.confO(5).

View File

@ -1,6 +1,6 @@
## Makefile.am
##
## (C) Copyright 2009,2016-2018 Fred Gleason <fredg@paravelsystems.com>
## (C) Copyright 2009-2019 Fred Gleason <fredg@paravelsystems.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License version 2 as
@ -29,10 +29,12 @@ moc_%.cpp: %.h
bin_PROGRAMS = rdalsaconfig
dist_rdalsaconfig_SOURCES = alsaitem.cpp alsaitem.h\
rdalsa.cpp rdalsa.h\
rdalsacard.cpp rdalsacard.h\
rdalsamodel.cpp rdalsamodel.h\
rdalsaconfig.cpp rdalsaconfig.h
nodist_rdalsaconfig_SOURCES = moc_rdalsaconfig.cpp
nodist_rdalsaconfig_SOURCES = moc_rdalsamodel.cpp\
moc_rdalsaconfig.cpp
rdalsaconfig_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @LIBALSA@ @QT4_LIBS@ -lQt3Support

View File

@ -2,7 +2,7 @@
//
// QListBoxItem for ALSA PCM devices.
//
// (C) Copyright 2009-2018 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2009-2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -29,38 +29,37 @@ AlsaItem::AlsaItem(Q3ListBox *listbox,const QString &text)
AlsaItem::AlsaItem(const QString &text)
: Q3ListBoxText(text)
{
alsa_card=-1;
alsa_device=-1;
alsa_card_number=-1;
alsa_pcm_number=-1;
}
AlsaItem::AlsaItem(const AlsaItem &item)
{
setText(item.text());
setCard(item.card());
setDevice(item.device());
setCardNumber(item.cardNumber());
setPcmNumber(item.pcmNumber());
}
int AlsaItem::card() const
int AlsaItem::cardNumber() const
{
return alsa_card;
return alsa_card_number;
}
void AlsaItem::setCard(int card)
void AlsaItem::setCardNumber(int cardnum)
{
alsa_card=card;
alsa_card_number=cardnum;
}
int AlsaItem::device() const
int AlsaItem::pcmNumber() const
{
return alsa_device;
return alsa_pcm_number;
}
void AlsaItem::setDevice(int device)
void AlsaItem::setPcmNumber(int pcmnum)
{
alsa_device=device;
alsa_pcm_number=pcmnum;
}

View File

@ -30,14 +30,13 @@ class AlsaItem : public Q3ListBoxText
AlsaItem(Q3ListBox *listbox,const QString &text=QString::null);
AlsaItem(const QString &text=QString::null);
AlsaItem(const AlsaItem &item);
int card() const;
void setCard(int card);
int device() const;
void setDevice(int device);
int cardNumber() const;
void setCardNumber(int cardnum);
int pcmNumber() const;
void setPcmNumber(int pcmnum);
private:
int alsa_card;
int alsa_device;
int alsa_card_number;
int alsa_pcm_number;
};

View File

@ -1,296 +0,0 @@
// rdalsa.cpp
//
// Abstract an ALSA configuration.
//
// (C) Copyright 2009-2018 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <stdlib.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#include <qstringlist.h>
#include <rdalsa.h>
RDAlsa::RDAlsa()
{
clear();
}
unsigned RDAlsa::cards() const
{
return card_ids.size();
}
QString RDAlsa::cardId(unsigned cardnum) const
{
if(cardnum>=card_ids.size()) {
return QString("[invalid card]");
}
return card_ids[cardnum];
}
QString RDAlsa::cardDriver(unsigned cardnum) const
{
if(cardnum>=card_drivers.size()) {
return QString("[invalid card]");
}
return card_drivers[cardnum];
}
QString RDAlsa::cardName(unsigned cardnum) const
{
if(cardnum>=card_names.size()) {
return QString("[invalid card]");
}
return card_names[cardnum];
}
QString RDAlsa::cardLongName(unsigned cardnum) const
{
if(cardnum>=card_long_names.size()) {
return QString("[invalid card]");
}
return card_long_names[cardnum];
}
QString RDAlsa::cardMixerName(unsigned cardnum) const
{
if(cardnum>=card_mixer_names.size()) {
return QString("[invalid card]");
}
return card_mixer_names[cardnum];
}
int RDAlsa::pcmDevices(unsigned cardnum) const
{
if(cardnum>=card_pcm_names.size()) {
return -1;
}
return card_pcm_names[cardnum].size();
}
QString RDAlsa::pcmName(unsigned cardnum,unsigned pcm) const
{
if(cardnum>=card_pcm_names.size()) {
return QString("[invalid pcm device]");
}
if(pcm>=card_pcm_names[cardnum].size()) {
return QString("[invalid pcm device]");
}
return card_pcm_names[cardnum][pcm];
}
int RDAlsa::rivendellCard(int slot) const
{
return card_rivendell_cards[slot];
}
void RDAlsa::setRivendellCard(int slot,int cardnum)
{
if(slot>=RD_MAX_CARDS) {
return;
}
card_rivendell_cards[slot]=cardnum;
}
int RDAlsa::rivendellDevice(int slot) const
{
return card_rivendell_devices[slot];
}
void RDAlsa::setRivendellDevice(int slot,int devnum)
{
if(slot>=RD_MAX_CARDS) {
return;
}
card_rivendell_devices[slot]=devnum;
}
bool RDAlsa::load(const QString &filename)
{
LoadSystemConfig();
return LoadAsoundConfig(filename);
}
bool RDAlsa::save(const QString &filename)
{
return SaveAsoundConfig(filename);
}
void RDAlsa::clear()
{
card_ids.clear();
card_drivers.clear();
card_names.clear();
card_long_names.clear();
card_mixer_names.clear();
card_pcm_names.clear();
for(unsigned i=0;i<RD_MAX_CARDS;i++) {
card_rivendell_cards[i]=-1;
card_rivendell_devices[i]=-1;
}
};
void RDAlsa::LoadSystemConfig()
{
snd_ctl_t *snd_ctl=NULL;
snd_ctl_card_info_t *card_info;
snd_pcm_info_t *pcm_info;
int card=0;
int pcm=0;
snd_ctl_card_info_malloc(&card_info);
snd_pcm_info_malloc(&pcm_info);
while(snd_ctl_open(&snd_ctl,QString().sprintf("hw:%d",card),0)>=0) {
snd_ctl_card_info(snd_ctl,card_info);
card_ids.push_back(snd_ctl_card_info_get_id(card_info));
card_drivers.push_back(snd_ctl_card_info_get_driver(card_info));
card_names.push_back(snd_ctl_card_info_get_name(card_info));
card_long_names.push_back(snd_ctl_card_info_get_longname(card_info));
card_mixer_names.push_back(snd_ctl_card_info_get_mixername(card_info));
std::vector<QString> pcms;
if(snd_ctl_pcm_info(snd_ctl,pcm_info)==0) {
pcm=0;
while(pcm>=0) {
pcms.push_back(QString().sprintf("%s [%02u]",
(const char *)snd_pcm_info_get_name(pcm_info),pcm+1));
snd_ctl_pcm_next_device(snd_ctl,&pcm);
}
}
card_pcm_names.push_back(pcms);
snd_ctl_close(snd_ctl);
card++;
}
}
bool RDAlsa::LoadAsoundConfig(const QString &filename)
{
FILE *f=NULL;
char line[1024];
int istate=0;
int port=0;
int card=0;
int device=0;
QStringList list;
if((f=fopen(filename,"r"))==NULL) {
return false;
}
while(fgets(line,1024,f)!=NULL) {
QString str=line;
str.replace("\n","");
if((str!=START_MARKER)&&(str!=END_MARKER)) {
switch(istate) {
case 0:
if(str.left(6)=="pcm.rd") {
port=str.mid(6,1).toInt();
istate=1;
}
else {
if(str.left(6)=="ctl.rd") {
istate=10;
}
else {
card_other_lines.push_back(str+"\n");
}
}
break;
case 1:
list=str.split(" ");
if(list[0]=="}") {
if((port>=0)&&(port<RD_MAX_CARDS)) {
card_rivendell_cards[port]=card;
card_rivendell_devices[port]=device;
}
card=0;
device=0;
istate=0;
}
else {
if(list.size()==2) {
if(list[0]=="card") {
card=list[1].toInt();
}
if(list[0]=="device") {
device=list[1].toInt();
}
}
}
break;
case 10:
if(str.left(1)=="}") {
istate=0;
}
break;
}
}
}
fclose(f);
return true;
}
bool RDAlsa::SaveAsoundConfig(const QString &filename)
{
FILE *f=NULL;
if((f=fopen(filename,"w"))==NULL) {
return false;
}
for(int i=0;i<card_other_lines.size();i++) {
fprintf(f,card_other_lines[i]);
}
fprintf(f,"%s\n",START_MARKER);
for(int i=0;i<RD_MAX_CARDS;i++) {
if((card_rivendell_cards[i]>=0)&&(card_rivendell_devices[i]>=0)) {
fprintf(f,"pcm.rd%d {\n",i);
fprintf(f," type hw\n");
fprintf(f," card %d\n",card_rivendell_cards[i]);
fprintf(f," device %d\n",card_rivendell_devices[i]);
fprintf(f,"}\n");
fprintf(f,"ctl.rd%d {\n",i);
fprintf(f," type hw\n");
fprintf(f," card %d\n",card_rivendell_cards[i]);
fprintf(f,"}\n");
}
}
fprintf(f,"%s\n",END_MARKER);
fclose(f);
return true;
}

View File

@ -1,69 +0,0 @@
// rdalsa.h
//
// Abstract an ALSA configuration.
//
// (C) Copyright 2009-2018 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDALSA_H
#define RDALSA_H
#include <vector>
#include <qstring.h>
#include <rd.h>
#define START_MARKER "# *** Start of Rivendell configuration generated by rdalsaconfig(1) ***"
#define END_MARKER "# *** End of Rivendell configuration generated by rdalsaconfig(1) ***"
class RDAlsa
{
public:
RDAlsa();
unsigned cards() const;
QString cardId(unsigned cardnum) const;
QString cardDriver(unsigned cardnum) const;
QString cardName(unsigned cardnum) const;
QString cardLongName(unsigned cardnum) const;
QString cardMixerName(unsigned cardnum) const;
int pcmDevices(unsigned cardnum) const;
QString pcmName(unsigned cardnum,unsigned pcm) const;
int rivendellCard(int slot) const;
void setRivendellCard(int slot,int cardnum);
int rivendellDevice(int slot) const;
void setRivendellDevice(int slot,int devnum);
bool load(const QString &filename);
bool save(const QString &filename);
void clear();
private:
void LoadSystemConfig();
bool LoadAsoundConfig(const QString &filename);
bool SaveAsoundConfig(const QString &filename);
std::vector<QString> card_ids;
std::vector<QString> card_drivers;
std::vector<QString> card_names;
std::vector<QString> card_long_names;
std::vector<QString> card_mixer_names;
std::vector<std::vector<QString> > card_pcm_names;
int card_rivendell_cards[RD_MAX_CARDS];
int card_rivendell_devices[RD_MAX_CARDS];
QStringList card_other_lines;
};
#endif // RDALSA_H

View File

@ -0,0 +1,114 @@
// rdalsacard.cpp
//
// Abstract ALSA 'card' information
//
// (C) Copyright 2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "rdalsacard.h"
RDAlsaCard::RDAlsaCard(snd_ctl_t *ctl,int index)
{
snd_ctl_card_info_t *card_info;
snd_pcm_info_t *pcm_info;
int pcm=0;
card_index=index;
snd_ctl_card_info_malloc(&card_info);
snd_pcm_info_malloc(&pcm_info);
snd_ctl_card_info(ctl,card_info);
card_id=QString(snd_ctl_card_info_get_id(card_info));
card_driver=QString(snd_ctl_card_info_get_driver(card_info));
card_name=QString(snd_ctl_card_info_get_name(card_info));
card_long_name=QString(snd_ctl_card_info_get_longname(card_info));
card_mixer_name=QString(snd_ctl_card_info_get_mixername(card_info));
if(snd_ctl_pcm_info(ctl,pcm_info)==0) {
pcm=0;
while(pcm>=0) {
card_pcm_names.push_back(snd_pcm_info_get_name(pcm_info)+
QString().sprintf("[%02d]",pcm+1));
snd_ctl_pcm_next_device(ctl,&pcm);
}
}
snd_pcm_info_free(pcm_info);
snd_ctl_card_info_free(card_info);
}
int RDAlsaCard::index() const
{
return card_index;
}
QString RDAlsaCard::id() const
{
return card_id;
}
QString RDAlsaCard::driver() const
{
return card_driver;
}
QString RDAlsaCard::name() const
{
return card_name;
}
QString RDAlsaCard::longName() const
{
return card_long_name;
}
QString RDAlsaCard::mixerName() const
{
return card_long_name;
}
QString RDAlsaCard::dump() const
{
QString ret=QString().sprintf("Card %d\n",index());
ret+=" ID: "+id()+"\n";
ret+=" Name: "+name()+"\n";
ret+=" LongName: "+longName()+"\n";
ret+=" MixerName: "+mixerName()+"\n";
for(int i=0;i<pcmQuantity();i++) {
ret+=QString().sprintf(" PCM[%d]: ",i)+pcmName(i)+"\n";
}
return ret;
}
int RDAlsaCard::pcmQuantity() const
{
return card_pcm_names.size();
}
QString RDAlsaCard::pcmName(int n) const
{
return card_pcm_names.at(n);
}

View File

@ -0,0 +1,54 @@
// rdalsacard.h
//
// Abstract ALSA 'card' information
//
// (C) Copyright 2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDALSACARD_H
#define RDALSACARD_H
#include <alsa/asoundlib.h>
#include <qstring.h>
#include <qstringlist.h>
class RDAlsaCard
{
public:
RDAlsaCard(snd_ctl_t *ctl,int index);
int index() const;
QString id() const;
QString driver() const;
QString name() const;
QString longName() const;
QString mixerName() const;
int pcmQuantity() const;
QString pcmName(int n) const;
QString dump() const;
private:
int card_index;
QString card_id;
QString card_driver;
QString card_name;
QString card_long_name;
QString card_mixer_name;
QStringList card_pcm_names;
};
#endif // RDALSACARD_H

View File

@ -2,7 +2,7 @@
//
// A Qt-based application to display info about ALSA cards.
//
// (C) Copyright 2009-2018 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2009-2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -25,6 +25,7 @@
#include <qapplication.h>
#include <qmessagebox.h>
#include <rd.h>
#include <rdcmd_switch.h>
#include <alsaitem.h>
@ -87,36 +88,21 @@ MainWidget::MainWidget(QWidget *parent)
label_font.setPixelSize(12);
//
// Available Devices
// ALSA Sound Devices
//
alsa_system_list=new Q3ListBox(this);
alsa_system_list=new QListView(this);
alsa_system_list->setFont(font);
alsa_system_list->setSelectionMode(QAbstractItemView::MultiSelection);
alsa_system_label=
new QLabel(alsa_system_list,tr("Available Sound Devices"),this);
new QLabel(alsa_system_list,tr("ALSA Sound Devices"),this);
alsa_system_label->setFont(label_font);
alsa_system_label->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
//
// Up Button
//
alsa_up_button=new RDTransportButton(RDTransportButton::Up,this);
connect(alsa_up_button,SIGNAL(clicked()),this,SLOT(upData()));
//
// Down Button
//
alsa_down_button=
new RDTransportButton(RDTransportButton::Down,this);
connect(alsa_down_button,SIGNAL(clicked()),this,SLOT(downData()));
//
// Selected Devices
//
alsa_config_list=new Q3ListBox(this);
alsa_config_list->setFont(font);
alsa_config_label=new QLabel(alsa_config_list,tr("Active Sound Devices"),this);
alsa_config_label->setFont(label_font);
alsa_config_label->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
alsa_description_label=new QLabel(this);
alsa_description_label->
setText(tr("Select the audio devices to dedicate for use with Rivendell. (Devices so dedicated will be unavailable for use with other applications.)"));
alsa_description_label->setFont(font);
alsa_description_label->setAlignment(Qt::AlignLeft|Qt::AlignTop);
alsa_description_label->setWordWrap(true);
//
// Save Button
@ -135,9 +121,9 @@ MainWidget::MainWidget(QWidget *parent)
//
// Load Available Devices and Configuration
//
alsa_alsa=new RDAlsa();
alsa_alsa->load(alsa_filename);
LoadList(alsa_system_list,alsa_config_list);
alsa_system_model=new RDAlsaModel();
alsa_system_list->setModel(alsa_system_model);
LoadConfig();
//
// Daemon Management
@ -168,7 +154,7 @@ MainWidget::~MainWidget()
QSize MainWidget::sizeHint() const
{
return QSize(400,300);
return QSize(400,400);
}
@ -178,33 +164,17 @@ QSizePolicy MainWidget::sizePolicy() const
}
void MainWidget::upData()
{
MoveItem(alsa_config_list,alsa_system_list);
}
void MainWidget::downData()
{
if(alsa_config_list->count()>=RD_MAX_CARDS) {
return;
}
MoveItem(alsa_system_list,alsa_config_list);
}
void MainWidget::saveData()
{
/*
AlsaItem *item=NULL;
for(int i=0;i<RD_MAX_CARDS;i++) {
if((item=(AlsaItem *)alsa_config_list->item(i))==NULL) {
alsa_alsa->setRivendellCard(i,-1);
alsa_alsa->setRivendellDevice(i,-1);
}
else {
alsa_alsa->setRivendellCard(i,item->card());
alsa_alsa->setRivendellDevice(i,item->device());
alsa_alsa->setRivendellCard(i,item->cardNumber());
}
}
if(!alsa_alsa->save(alsa_filename)) {
@ -214,6 +184,10 @@ void MainWidget::saveData()
return;
}
StartDaemons();
*/
SaveConfig();
qApp->quit();
}
@ -227,14 +201,10 @@ void MainWidget::cancelData()
void MainWidget::resizeEvent(QResizeEvent *e)
{
alsa_system_label->setGeometry(20,5,size().width()-20,20);
alsa_system_label->setGeometry(10,5,size().width()-20,20);
alsa_description_label->setGeometry(10,25,size().width()-20,50);
alsa_system_list->
setGeometry(10,25,size().width()-20,(size().height()-120)/2);
alsa_up_button->setGeometry(size().width()-120,size().height()/2-28,50,30);
alsa_down_button->setGeometry(size().width()-60,size().height()/2-28,50,30);
alsa_config_label->setGeometry(20,size().height()/2-10,size().width()/2,20);
alsa_config_list->setGeometry(10,size().height()/2+10,
size().width()-20,(size().height()-120)/2);
setGeometry(10,75,size().width()-20,size().height()-130);
alsa_save_button->
setGeometry(size().width()-120,size().height()-40,50,30);
alsa_cancel_button->
@ -263,93 +233,123 @@ void MainWidget::closeEvent(QCloseEvent *e)
}
void MainWidget::LoadList(Q3ListBox *system,Q3ListBox *config)
void MainWidget::LoadConfig()
{
for(unsigned i=0;i<alsa_alsa->cards();i++) {
for(int j=0;j<alsa_alsa->pcmDevices(i);j++) {
if(PcmUnused(i,j)) {
AlsaItem *item=
new AlsaItem(alsa_alsa->cardLongName(i)+" - "+
alsa_alsa->pcmName(i,j));
item->setCard(i);
item->setDevice(j);
system->insertItem(item);
}
}
}
system->sort();
FILE *f=NULL;
char line[1024];
int istate=0;
int port=0;
QString card_id=0;
int device=0;
QStringList list;
bool active_line=false;
QModelIndex index;
for(int i=0;i<RD_MAX_CARDS;i++) {
if(alsa_alsa->rivendellCard(i)>=0) {
AlsaItem *item=
new AlsaItem(alsa_alsa->cardLongName(alsa_alsa->rivendellCard(i))+" - "+
alsa_alsa->pcmName(alsa_alsa->rivendellCard(i),
alsa_alsa->rivendellDevice(i)));
item->setCard(alsa_alsa->rivendellCard(i));
item->setDevice(alsa_alsa->rivendellDevice(i));
config->insertItem(item);
}
}
config->sort();
}
bool MainWidget::PcmUnused(int card,int device)
{
for(int i=0;i<RD_MAX_CARDS;i++) {
if((card==alsa_alsa->rivendellCard(i))&&
(device==alsa_alsa->rivendellDevice(i))) {
return false;
}
}
return true;
}
void MainWidget::MoveItem(Q3ListBox *src,Q3ListBox *dest)
{
AlsaItem *item=(AlsaItem *)src->selectedItem();
if(item==NULL) {
if((f=fopen(RD_ASOUNDRC_FILE,"r"))==NULL) {
return;
}
dest->insertItem(new AlsaItem(*item)); // Force a deep copy
dest->sort();
delete item;
while(fgets(line,1024,f)!=NULL) {
QString str=line;
str.replace("\n","");
if(str==START_MARKER) {
active_line=true;
}
if(str==END_MARKER) {
active_line=false;
}
if((str!=START_MARKER)&&(str!=END_MARKER)) {
if(active_line) {
switch(istate) {
case 0:
if(str.left(6)=="pcm.rd") {
port=str.mid(6,1).toInt();
istate=1;
}
else {
if(str.left(6)=="ctl.rd") {
istate=10;
}
else {
alsa_other_lines.push_back(str+"\n");
}
}
break;
case 1:
list=str.split(" ",QString::SkipEmptyParts);
if(list[0]=="}") {
if((port>=0)&&(port<RD_MAX_CARDS)) {
index=alsa_system_model->indexOf(card_id,device);
if(index.isValid()) {
alsa_system_list->selectionModel()->
select(index,QItemSelectionModel::Select);
}
}
card_id="";
device=0;
istate=0;
}
else {
if(list.size()==2) {
if(list[0]=="card") {
card_id=list[1].trimmed();
}
if(list[0]=="device") {
device=list[1].toInt();
}
}
}
break;
case 10:
if(str.left(1)=="}") {
istate=0;
}
break;
}
}
else {
alsa_other_lines.push_back(str+"\n");
}
}
}
fclose(f);
}
Autogen::Autogen(QObject *parent)
void MainWidget::SaveConfig() const
{
StopDaemons();
QString tempfile=QString(RD_ASOUNDRC_FILE)+"-temp";
FILE *f=NULL;
//
// Load Available Devices
//
RDAlsa *alsa=new RDAlsa();
alsa->load(alsa_filename);
//
// Build Configuration
//
int slot=0;
for(unsigned i=0;i<alsa->cards();i++) {
for(int j=0;j<alsa->pcmDevices(i);j++) {
alsa->setRivendellCard(slot,i);
alsa->setRivendellDevice(slot,j);
slot++;
if((f=fopen(tempfile.toUtf8(),"w"))==NULL) {
return;
}
for(int i=0;i<alsa_other_lines.size();i++) {
fprintf(f,alsa_other_lines.at(i));
}
//
// Save Configuration
//
if(!alsa->save(alsa_filename)) {
exit(256);
fprintf(f,"%s\n",START_MARKER);
QModelIndexList indexes=alsa_system_list->selectionModel()->selectedIndexes();
for(int i=0;i<indexes.size();i++) {
fprintf(f,"pcm.rd%d {\n",i);
fprintf(f," type hw\n");
fprintf(f," card %s\n",
(const char *)alsa_system_model->card(indexes.at(i))->id().toUtf8());
fprintf(f," device %d\n",alsa_system_model->pcmNumber(indexes.at(i)));
if(alsa_system_model->card(indexes.at(i))->id()=="Axia") {
fprintf(f," channels 2\n");
}
fprintf(f,"}\n");
fprintf(f,"ctl.rd%d {\n",i);
fprintf(f," type hw\n");
fprintf(f," card %s\n",
(const char *)alsa_system_model->card(indexes.at(i))->id().toUtf8());
fprintf(f,"}\n");
}
fprintf(f,"%s\n",END_MARKER);
StartDaemons();
exit(0);
fclose(f);
rename(tempfile.toUtf8(),RD_ASOUNDRC_FILE);
}
@ -373,15 +373,6 @@ int main(int argc,char *argv[])
}
}
//
// Autogenerate a full configuration
//
if(alsa_autogen) {
QApplication a(argc,argv,false);
new Autogen();
return a.exec();
}
//
// Start GUI
//

View File

@ -2,7 +2,7 @@
//
// A Qt-based application to display info about ALSA cards.
//
// (C) Copyright 2009-2018 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2009-2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -22,13 +22,13 @@
#define RDALSACONFIG_H
#include <qwidget.h>
#include <q3listbox.h>
#include <qlistview.h>
#include <qlabel.h>
#include <rdtransportbutton.h>
#include <rd.h>
#include <rdalsa.h>
#include "rdalsamodel.h"
#define RDALSACONFIG_USAGE "[--asoundrc-file=<filename>] [--autogen] [--manage-daemons]\n\nGenerate an ALSA sound card configuration for Rivendell.\n\nThe following options are available:\n\n --asoundrc-file=<filename>\n Read and write configuration from <filename> (default value \n \"/etc/asound.conf\").\n\n --autogen\n Generate and save a configuration containing all available PCM devices\n and then exit.\n\n --manage-daemons\n Restart the Rivendell daemons as necessary to make configuration\n changes active (requires root permission).\n\n"
@ -45,8 +45,6 @@ class MainWidget : public QWidget
QSizePolicy sizePolicy() const;
private slots:
void upData();
void downData();
void saveData();
void cancelData();
@ -55,26 +53,15 @@ class MainWidget : public QWidget
void closeEvent(QCloseEvent *e);
private:
void LoadList(Q3ListBox *system,Q3ListBox *config);
bool PcmUnused(int card,int device);
void MoveItem(Q3ListBox *src,Q3ListBox *dest);
void LoadConfig();
void SaveConfig() const;
QLabel *alsa_system_label;
Q3ListBox *alsa_system_list;
QLabel *alsa_config_label;
Q3ListBox *alsa_config_list;
RDTransportButton *alsa_up_button;
RDTransportButton *alsa_down_button;
QLabel *alsa_description_label;
QListView *alsa_system_list;
RDAlsaModel *alsa_system_model;
QStringList alsa_other_lines;
QPushButton *alsa_save_button;
QPushButton *alsa_cancel_button;
RDAlsa *alsa_alsa;
};
class Autogen : public QObject
{
Q_OBJECT
public:
Autogen(QObject *parent=0);
};

View File

@ -0,0 +1,153 @@
// rdalsamodel.cpp
//
// Abstract an ALSA configuration.
//
// (C) Copyright 2009-2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <stdlib.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#include <qstringlist.h>
#include <rdalsamodel.h>
RDAlsaModel::RDAlsaModel(QObject *parent)
: QAbstractListModel(parent)
{
LoadSystemConfig();
}
int RDAlsaModel::rowCount(const QModelIndex &parent) const
{
int rows=0;
for(int i=0;i<model_alsa_cards.size();i++) {
rows+=model_alsa_cards.at(i)->pcmQuantity();
}
return rows;
}
QVariant RDAlsaModel::data(const QModelIndex &index,int role) const
{
int row=index.row();
switch((Qt::ItemDataRole)role) {
case Qt::DisplayRole:
return QVariant(model_alsa_cards.at(model_card_index.at(row))->name()+" - "+
model_alsa_cards.at(model_card_index.at(row))->
pcmName(model_pcm_index.at(row)));
break;
case Qt::DecorationRole:
case Qt::EditRole:
case Qt::ToolTipRole:
case Qt::StatusTipRole:
case Qt::WhatsThisRole:
case Qt::SizeHintRole:
case Qt::FontRole:
case Qt::TextAlignmentRole:
case Qt::BackgroundColorRole:
case Qt::TextColorRole:
case Qt::CheckStateRole:
case Qt::AccessibleTextRole:
case Qt::AccessibleDescriptionRole:
case Qt::InitialSortOrderRole:
case Qt::DisplayPropertyRole:
case Qt::DecorationPropertyRole:
case Qt::ToolTipPropertyRole:
case Qt::StatusTipPropertyRole:
case Qt::WhatsThisPropertyRole:
case Qt::UserRole:
break;
}
return QVariant();
}
QVariant RDAlsaModel::headerData(int section,Qt::Orientation orient,
int role) const
{
switch(orient) {
case Qt::Horizontal:
return QVariant(tr("ALSA Devices"));
case Qt::Vertical:
break;
}
return QVariant();
}
QModelIndex RDAlsaModel::indexOf(const QString &card_id,int pcm_num) const
{
bool ok=false;
int cardnum=card_id.toUInt(&ok);
if(ok) {
for(int i=0;i<model_card_index.size();i++) {
if((model_card_index.at(i)==cardnum)&&
(model_pcm_index.at(i)==pcm_num)) {
return createIndex(i,0);
}
}
}
else {
for(int i=0;i<model_card_index.size();i++) {
if((model_alsa_cards.at(model_card_index.at(i))->id()==card_id)&&
(model_pcm_index.at(i)==pcm_num)) {
return createIndex(i,0);
}
}
}
return QModelIndex();
}
RDAlsaCard *RDAlsaModel::card(const QModelIndex &index) const
{
return model_alsa_cards.at(model_card_index.at(index.row()));
}
int RDAlsaModel::pcmNumber(const QModelIndex &index) const
{
return model_pcm_index.at(index.row());
}
void RDAlsaModel::LoadSystemConfig()
{
snd_ctl_t *snd_ctl=NULL;
int index=0;
while(snd_ctl_open(&snd_ctl,QString().sprintf("hw:%d",index),0)>=0) {
model_alsa_cards.push_back(new RDAlsaCard(snd_ctl,index));
for(int i=0;i<model_alsa_cards.back()->pcmQuantity();i++) {
model_card_index.push_back(index);
model_pcm_index.push_back(i);
}
snd_ctl_close(snd_ctl);
index++;
}
}

View File

@ -0,0 +1,56 @@
// rdalsamodel.h
//
// Abstract an ALSA configuration.
//
// (C) Copyright 2009-2018 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef RDALSAMODEL_H
#define RDALSAMODEL_H
#include <QAbstractListModel>
#include <qlist.h>
#include <qstring.h>
#include <rd.h>
#include "rdalsacard.h"
#define START_MARKER "# *** Start of Rivendell configuration generated by rdalsaconfig(1) ***"
#define END_MARKER "# *** End of Rivendell configuration generated by rdalsaconfig(1) ***"
class RDAlsaModel : public QAbstractListModel
{
Q_OBJECT;
public:
RDAlsaModel(QObject *parent=0);
int rowCount(const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index,int role=Qt::DisplayRole) const;
QVariant headerData(int section,Qt::Orientation orient,
int role=Qt::DisplayRole) const;
QModelIndex indexOf(const QString &card_id,int pcm_num) const;
RDAlsaCard *card(const QModelIndex &index) const;
int pcmNumber(const QModelIndex &index) const;
private:
void LoadSystemConfig();
QList<RDAlsaCard *> model_alsa_cards;
QList<int> model_card_index;
QList<int> model_pcm_index;
};
#endif // RDALSAMODEL_H