LINUX.ORG.RU

Проблема с ALSA


0

0

Помогите пожалуйста, куда копать?
При изменении Volume - segmentation fault
Исходники .......
pro.pro

TARGET = pro
TEMPLATE = app
SOURCES += main.cpp \
    mainwindow.cpp \
    alsa.cpp
HEADERS += mainwindow.h \
    alsa.h
FORMS += 
LIBS += -lasound
alsa.h
#ifndef __ALSA_H__
#define __ALSA_H__

#include <qobject.h>
#include <qstring.h>
#include <qmap.h>
#include <QDebug>

#include <alsa/asoundlib.h>

#define REPORT qDebug() << sig << ' '

class alsaMixer
{
public:
    alsaMixer();
    virtual ~alsaMixer(void);

    virtual int probeDevices(void);
    virtual int setVolume(int LetftChannel, int RightChannel);
    virtual int volumeLeft(void);
    virtual int volumeRight(void);

    virtual int setMuted(bool mute);
    virtual bool muted(void);

private:
    int useCardMixerElement(const QString &HCTL_id, QString &mixer_element);
    snd_mixer_t *attachMixer(const QString &HCTL_id);
    int detachMixer(snd_mixer_t *mixer, const char *HCTL_id);
    int loadMixerElements(snd_mixer_t *mixer);
    QMap<int, QString> probed_cards;
    QMap<snd_mixer_elem_t *, QString> mixer_elements; 

    QString active_HCTL;
    QString active_mixer_element;
    snd_mixer_t *active_mixer;
    snd_mixer_elem_t *active_element;
    int volume_left, volume_right;
    bool muted_flag;
};

#endif
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtCore>
#include <QtGui>
#include <QDebug>
#include "alsa.h"

class alsaMixer;

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    QSlider *volumeSlider;
    alsaMixer *amixer;

private slots:
    void setVolume(int volume);
};

#endif // MAINWINDOW_H

продолжение

alsa.cpp

#include "alsa.h"

alsaMixer::alsaMixer()
{
	active_HCTL.truncate(0);
	active_mixer_element.truncate(0);
	active_mixer = NULL;
	active_element = NULL;
	muted_flag = false;
        volume_left = 0;
        volume_right = 0;
        QString hctl = "hw:00";
        QString elem = "Master";
        useCardMixerElement(hctl,elem);
}

alsaMixer::~alsaMixer()
{
    detachMixer(active_mixer, active_HCTL.toLocal8Bit());
}

snd_mixer_t *alsaMixer::attachMixer(const QString &HCTL_id)
{
	const char *sig="[attachMixer()]";
	snd_mixer_t *tmp_mixer;
	int retcode;

	REPORT << "attempting to attach a mixer to " << HCTL_id << endl;

	if((retcode = snd_mixer_open(&tmp_mixer, 0)) != 0) {
		REPORT << "ERROR: snd_mixer_open failed: " << strerror(-retcode) << endl;
		return(NULL);
	}

        if((retcode = snd_mixer_attach(tmp_mixer, HCTL_id.toLocal8Bit())) != 0) {
		REPORT << "ERROR: snd_mixer_attach failed: " << strerror(-retcode) << endl;
		snd_mixer_close(tmp_mixer);
		return(NULL);
	}

	snd_mixer_selem_register(tmp_mixer, NULL, NULL);

        if(alsaMixer::loadMixerElements(tmp_mixer) != 0) {
                alsaMixer::detachMixer(tmp_mixer, active_HCTL.toLocal8Bit());
		active_HCTL.truncate(0);
		return(NULL);
	}

	REPORT << "mixer attached successfully to " << HCTL_id << endl;

	return(tmp_mixer);
}

int alsaMixer::detachMixer(snd_mixer_t *mixer, const char *HCTL_id)
{
	const char *sig="[detachMixer()]";
	int retval;

	if( (active_mixer == NULL) || active_HCTL.isEmpty() ) {
	    return 0;
	}

	REPORT << "detaching mixer from " << HCTL_id << endl;

	snd_mixer_free(mixer);

	if((retval = snd_mixer_detach(mixer, HCTL_id)) != 0) {
		REPORT << "ERROR: snd_mixer_detach failed: " << strerror(-retval) << endl;
		return(retval);
	}

	if((retval = snd_mixer_close(mixer)) != 0) {
		REPORT << "ERROR: snd_mixer_close failed: " << strerror(-retval) << endl;
		return(retval);
	}

	REPORT << "mixer detached successfully from " << HCTL_id << endl;

	return 0;
}

int alsaMixer::loadMixerElements(snd_mixer_t *mixer)
{
	const char *sig="[loadMixerElements()]";
	snd_mixer_elem_t *mixer_element;
	snd_mixer_selem_id_t *sid;
	int retval, element_count = 0;

	REPORT << "discovering mixer elements" << endl;

	snd_mixer_selem_id_alloca(&sid);

	mixer_elements.clear();

	if((retval = snd_mixer_load(mixer)) != 0) {
		REPORT << "ERROR: snd_mixer_load failed: " << strerror(-retval) << endl;
		return(retval);
	}

	for(mixer_element = snd_mixer_first_elem(mixer) ; mixer_element ;
        mixer_element = snd_mixer_elem_next(mixer_element)) {
		element_count++;
		snd_mixer_selem_get_id(mixer_element, sid);

		mixer_elements.insert(mixer_element, snd_mixer_selem_id_get_name(sid));
		REPORT << " + " << snd_mixer_selem_id_get_name(sid) << endl;
	}

	REPORT << " elements discovered : " << element_count << endl;

	if (mixer_elements.count() == 0) {
        return -1;
	}
	REPORT << " playback elements : " << mixer_elements.count() << endl;

	return(0);
}

int alsaMixer::probeDevices(void)
{
	const char *sig="[probeDevices()]";
	int card_id = -1;
	int retval;

	REPORT << "querying ALSA driver for soundcards" << endl;

	probed_cards.clear();

	while((retval = snd_card_next(&card_id)) == 0) {
		if(card_id == -1) break;

		probed_cards.insert(card_id, QString("hw:%1").arg(card_id));
	}

	if(retval != 0) {
		REPORT << "ERROR snd_card_next failed: "  << strerror(-retval) << endl;
	}

	REPORT << "ALSA driver reported " << probed_cards.size() << " cards" << endl;

	return(0);
}

int alsaMixer::useCardMixerElement(const QString &HCTL_id, QString &mixer_element)
{
	const char *sig="[useCardMixerElement()]";
	QMap<snd_mixer_elem_t *, QString>::const_iterator it;

	REPORT << "request mixer element " << mixer_element << " on " << HCTL_id
           << endl;

	if(!active_HCTL.isEmpty() && active_mixer != NULL) {
                if(alsaMixer::detachMixer(active_mixer, active_HCTL.toLocal8Bit()) != 0)
			return(1);
		active_HCTL.truncate(0);
		active_mixer = NULL;
	}

        if((active_mixer = alsaMixer::attachMixer(HCTL_id)) == NULL)
		return(1);
	active_HCTL = HCTL_id;

	for(it = mixer_elements.constBegin() ; it != mixer_elements.constEnd() ; ++it) {
                if(mixer_element != it.value()) continue;
		break;
	}

	active_element = it.key();
        active_mixer_element = it.value();

	REPORT << "mixer element " << mixer_element << " acquired" << endl;
	return(0);
}


bool alsaMixer::muted(void)
{
	return(muted_flag);
}

int alsaMixer::setMuted(bool mute)
{
	const char *sig="[setMuted()]";
	int playback_status;

	if(active_element == NULL){
		REPORT << "ERROR: no active mixer element present" << endl;
		return(1);
	}

 	snd_mixer_selem_get_playback_switch(active_element,
                                        SND_MIXER_SCHN_FRONT_LEFT, &playback_status);

	if(!(playback_status ^ mute)) {
		snd_mixer_selem_set_playback_switch_all(active_element, !playback_status);
		muted_flag = mute;
 	}

	REPORT << mixer_elements[active_element] << " on " << active_HCTL
           << " muted=" << muted_flag << endl;
	return 0;
}

int alsaMixer::setVolume(int LeftVolume, int RightVolume)
{
    const char *sig="[setVolume()]";
	long min, max, vol;

	if(active_element == NULL){
		REPORT << "ERROR: no active mixer element present" << endl;
		return(1);
	}

        if(alsaMixer::muted())
                alsaMixer::setMuted(false);

	snd_mixer_selem_get_playback_volume_range(active_element, &min, &max);

	vol = ((LeftVolume * (max - min)) / 100) + min;
	snd_mixer_selem_set_playback_volume(active_element,
                                        SND_MIXER_SCHN_FRONT_LEFT, vol);
	volume_left = LeftVolume;

	vol = ((RightVolume * (max - min)) / 100) + min;
	snd_mixer_selem_set_playback_volume(active_element,
                                        SND_MIXER_SCHN_FRONT_RIGHT, vol);
	volume_right = RightVolume;

	return(0);
}

int alsaMixer::volumeLeft(void)
{
	return(volume_left);
}

int alsaMixer::volumeRight(void)
{
	return(volume_right);
}
main.cpp
#include "mainwindow.h"
#include <QtGui>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow w;
    w.show();

    return app.exec();
}
mainwindow.cpp
#include "mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
{       
    volumeSlider = new QSlider(Qt::Horizontal,this);
    volumeSlider->setRange(0, 100);
    volumeSlider->setSliderPosition(20);
    alsaMixer *amixer = new alsaMixer();
    int value = 100;
    volumeSlider->setValue(value);
    connect(volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(setVolume(int)));
    amixer->setVolume(value,value);
}

void MainWindow::setVolume(int value)
{
    qDebug() << value;
    amixer->setVolume(value,value);
}

SergeBegger
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.