/*
* This file is a part of VyQChat.
*
* Copyright (C) 2002-2004 Pawel Stolowski <yogin@linux.bydg.org>
*
* VyQChat is free software; you can redestribute it and/or modify it
* under terms of GNU General Public License by Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY. See GPL for more details.
*/
#include "config.h"
#include "sound.h"
#include "settings.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <qapplication.h>
#include <qfile.h>
#include <qprocess.h>
#include <qglobal.h>
Sound::SoundType Sound::sndtype;
SoundSystem *Sound::sndsys = NULL;
static void sigchld_handler(int s)
{
wait(NULL);
}
bool Sound::reload_samples(Settings &settings)/*{{{*/
{
return sndsys->reload_samples(settings);
}/*}}}*/
bool Sound::init(Settings *settings)/*{{{*/
{
sndtype = settings->getSoundType();
switch (sndtype)
{
case NoSound:
sndsys = new SoundSystem();
break;
case PCSpeaker:
sndsys = new SoundPCSpeaker();
break;
case Command:
sndsys = new SoundCommand();
break;
case Arts:
sndsys = new SoundArts();
break;
case LibAo:
sndsys = new SoundLibAo();
break;
default: return false;
}
if (!sndsys)
return false;
bool status = sndsys->init();
if (!status)
{
delete sndsys;
sndsys = new SoundPCSpeaker();
status = sndsys->init();
}
if (status)
{
sndsys->reload_samples(*settings);
signal(SIGCHLD, sigchld_handler);
}
return status;
}/*}}}*/
void Sound::close()/*{{{*/
{
if (sndsys)
sndsys->close();
}/*}}}*/
void Sound::play(VyEvent evt)/*{{{*/
{
if (sndsys)
sndsys->play(evt);
}/*}}}*/
const QString& Sound::error()/*{{{*/
{
return sndsys->errstr;
}/*}}}*/
/*
* Sound systems base
*/
SoundSystem::SoundSystem()/*{{{*/
{
for (int i=0; i<EventDummy; i++)
sample[i] = new QByteArray(0);
}/*}}}*/
SoundSystem::~SoundSystem()/*{{{*/
{
for (int i=0; i<EventDummy; i++)
delete sample[i];
}/*}}}*/
bool SoundSystem::reload_samples(Settings &settings)/*{{{*/
{
# ifdef HAVE_SNDFILE
bool status = true;
for (int i=0; i<EventDummy; i++)
{
sfinf[i].format = 0;
SNDFILE *f = sf_open(settings.getSampleFileName(static_cast<VyEvent>(i)).latin1(), SFM_READ, &sfinf[i]);
if (f)
{
sample[i]->resize(sfinf[i].channels * sfinf[i].frames * sizeof(short));
sf_readf_short(f, reinterpret_cast<short *>(sample[i]->data()), sfinf[i].frames);
sf_close(f);
}
else
{
status = false;
}
}
return status;
# else
return false;
# endif
}/*}}}*/
/*
* PC Speaker
*/
bool SoundPCSpeaker::init()/*{{{*/
{
return true;
}/*}}}*/
void SoundPCSpeaker::play(VyEvent evt)/*{{{*/
{
QApplication::beep();
}/*}}}*/
void SoundPCSpeaker::close()/*{{{*/
{
}/*}}}*/
/*
* LibAo
*/
bool SoundLibAo::init()/*{{{*/
{
# ifdef HAVE_LIBAO
ao_initialize();
drv = ao_default_driver_id();
return true;
# else
errstr = QString("No libao support compiled");
return false;
# endif
}/*}}}*/
void SoundLibAo::play(VyEvent evt)/*{{{*/
{
# ifdef HAVE_LIBAO
# ifdef HAVE_SNDFILE
if (fork() == 0)
{
ao_sample_format frmt;
frmt.bits = sizeof(short) << 3;
frmt.channels = sfinf[evt].channels;
frmt.rate = sfinf[evt].samplerate;
frmt.byte_format = AO_FMT_NATIVE;
ao_device* dev = ao_open_live(drv, &frmt, NULL);
ao_play(dev, sample[evt]->data(), sample[evt]->size());
ao_close(dev);
ao_shutdown();
_exit(0);
}
# endif
# endif
}/*}}}*/
void SoundLibAo::close()/*{{{*/
{
# ifdef HAVE_LIBAO
ao_shutdown();
# endif
}/*}}}*/
/*
* ARTS
*/
bool SoundArts::init()/*{{{*/
{
# ifdef HAVE_ARTS
/* int err;
if ((err = arts_init()) < 0)
{
errstr = arts_error_text(err);
return false;
}*/
# else
errstr = "no aRtS support compiled";
return false;
# endif
return true;
}/*}}}*/
void SoundArts::play(VyEvent evt)/*{{{*/
{
# ifdef HAVE_ARTS
# ifdef HAVE_SNDFILE
if (fork() == 0)
{
arts_init();
arts_stream_t str = arts_play_stream(sfinf[evt].samplerate, sizeof(short)<<3, sfinf[evt].channels, "vyqchat");// + QString::number(getpid()));
arts_write(str, sample[evt]->data(), sample[evt]->size());
//if (status<0)
// qWarning("arts_write error: %s", arts_error_text(status));
arts_close_stream(str);
arts_free();
_exit(0);
}
# endif
# endif
}/*}}}*/
void SoundArts::close()/*{{{*/
{
# ifdef HAVE_ARTS
//arts_free();
# endif
}/*}}}*/
/*
* COMMAND
*/
bool SoundCommand::reload_samples(Settings &settings)/*{{{*/
{
const QStringList cmd = QStringList::split(' ', settings.getPlayCommand());
for (int i=0; i<EventDummy; i++)
{
arg[i].clear();
arg[i] = cmd;
arg[i].append(settings.getSampleFileName(static_cast<VyEvent>(i)));
}
return true;
}/*}}}*/
bool SoundCommand::init()/*{{{*/
{
return true;
}/*}}}*/
void SoundCommand::play(VyEvent evt)/*{{{*/
{
QProcess *proc = new QProcess(arg[evt], NULL);
QObject::connect(proc, SIGNAL(processExited()), proc, SLOT(deleteLater()));
if (!proc->start())
qWarning("cannot run play command");
}/*}}}*/
syntax highlighted by Code2HTML, v. 0.9.1