lms-audio/src/audiomotor.cpp
Santi Noreña 5cfd9f7a10 Fixed pan bug (again)
Reduced the debug output
The volune range is 0 -100 and dbtorms is used in pure data to make the
scale logarithm
2014-07-15 20:03:14 +02:00

380 lines
9.5 KiB
C++

#include "audiomotor.h"
#define PAUSE 2
#define PLAY 0
#define STOP 1
#define MAX_DATA = 1024;
AudioMotor *AudioMotor::_instance = 0;
AudioMotor *AudioMotor::getInstance() {
if (_instance == 0) {
_instance = new AudioMotor();
Q_CHECK_PTR(_instance);
}
return _instance;
}
AudioMotor::AudioMotor(QObject *parent) :
QObject(parent),
m_startaudio(0),
m_writePD(NULL),
m_readPD(NULL),
m_pd_audio(NULL),
m_connectedSocket(NULL),
m_gui(true)
{
qsrand(qrand());
qDebug() << "Init MotorAudio";
}
AudioMotor::~AudioMotor()
{
close();
}
/** Init the engine
*/
bool AudioMotor::init()
{
/* Sets the socket an connections for the comunication with PD
QFile socket(SOCKET);
if (socket.exists())
{
socket.remove();
}*/
// Socket para mandar órdenes a Pure Data
m_writePD = new QTcpSocket(this);
Q_CHECK_PTR(m_writePD);
connect(m_writePD, SIGNAL(connected()),this, SLOT(newConexion()));
connect(m_writePD, SIGNAL(error(QAbstractSocket::SocketError)) , this, SLOT(errorWrite(QAbstractSocket::SocketError)));
// Servidor para recibir feedback de Pure Data
m_readPD = new QTcpServer(this);
Q_CHECK_PTR(m_readPD);
connect(m_readPD, SIGNAL(newConnection()),this, SLOT(newPeer()));
if (m_readPD->listen(QHostAddress::LocalHost, PDPORT)) {
qDebug(QString("AudioMotor| Listening to PD on TCP port %1").arg(PDPORT).toLatin1());
} else {
qErrnoWarning(QString("AudioMotor::init() can not init TCP Server on port %1").arg(PDPORT).toLatin1());
emit toTerminal(QString("AudioMotor::init() can not init TCP Server on port)" + PDPORT));
}
// Start the pd process an set up PD
m_pd_audio = new QProcess(this);
connect(m_pd_audio, SIGNAL(readyReadStandardError()), this, SLOT(stdout()));
connect(m_pd_audio, SIGNAL(finished(int)), this, SLOT(restartAudio()));
QString arguments;
// arguments.append("./puredata/pd -alsa -channels 2 -audiodev 1 -stderr -nostdpath -path ./puredata/externals/ -open ./puredata/lms-audio.pd ");
arguments.append("./puredata/pd -channels 2 -stderr -nostdpath -path ./puredata/externals/ -open ./puredata/lms-audio.pd ");
if (!m_gui)
arguments.append("-nogui");
m_pd_audio->start(arguments);
if (m_pd_audio->waitForStarted(3000)){
qDebug("AudioMotor| PD started");
emit toTerminal(QString("AudioMotor| PD started"));
}
else
{
emit toTerminal("AudioMotor| Can not init PD");
qErrnoWarning("AudioMotor| Can not init PD");
return false;
}
m_startaudio++;
return true;
}
/** Close the engine
*/
bool AudioMotor::close()
{
disconnect(m_pd_audio, SIGNAL(readyReadStandardError()), this, SLOT(stdout()));
disconnect(m_pd_audio, SIGNAL(finished(int)), this, SLOT(restartAudio()));
m_pd_audio->terminate();
m_pd_audio->waitForFinished(1000);
delete m_pd_audio;
m_pd_audio = NULL;
if (m_writePD != NULL)
{
disconnect(m_writePD, SIGNAL(connected()),this, SLOT(newConexion()));
m_writePD->close();
delete m_writePD;
m_writePD = NULL;
}
if (m_readPD != NULL)
{
disconnect(m_readPD, SIGNAL(newConnection()),this, SLOT(newPeer()));
m_readPD->close();
delete m_readPD;
m_readPD = NULL;
}
/*
QFile socket(SOCKET);
if (socket.exists())
{
socket.remove();
}*/
}
/** Set the numbers of layers
*/
void AudioMotor::setLayers (int layers){
}
/** Get the number of layers
*/
int AudioMotor::getlayers(){
}
/** Load a file in memory
*
*/
bool AudioMotor::load(int layer, QString file)
{
if (!QFile::exists(file))
return false;
QString message = tr("%1 ").arg(layer +201);
message.append("open ");
message.append(file);
message.append(";");
qDebug() << "AudioMotor::load " << message;
if (QAbstractSocket::ConnectedState != m_writePD->state())
{
qErrnoWarning("AudioMotor::load(): Socket not conected: ");
emit toTerminal("AudioMotor::load(): Socket not connectedt");
return false;
}
if (message.size() != m_writePD->write(message.toAscii().constData(), message.size()))
{
qErrnoWarning("AudioMotor::load(): Can not write to socket");
emit toTerminal("AudioMotor::load(): Can not write to socket");
return false;
}
return true;
}
/** Starts the playback at start position
*
*/
bool AudioMotor::play(int layer)
{
QString buffer = tr("%1 %2 %3;").arg(layer).arg(PLAYBACK).arg(PLAY);
if (!sendPacket(buffer.toAscii().constData(), buffer.size()))
{
errorSending();
return false;
}
return true;
}
/** Unpause the playback
*/
bool AudioMotor::pause(int layer)
{
QString buffer = tr("%1 %2 %3;").arg(layer).arg(PLAYBACK).arg(PAUSE);
if (!sendPacket(buffer.toAscii().constData(), buffer.size()))
{
errorSending();
return false;
}
return true;
}
/** Stops/pause the playback
*
*/
bool AudioMotor::stop(int layer)
{
QString buffer = tr("%1 %2 %3;").arg(layer).arg(PLAYBACK).arg(STOP);
if (!sendPacket(buffer.toAscii().constData(), buffer.size()))
{
errorSending();
return false;
}
return true;
}
/** Sets the start playback position
*
*/
void AudioMotor::setEntryPoint(int layer, int entry)
{
}
/** Sets the final playback position
*
*/
void AudioMotor::setExitPoint(int layer, int exit)
{
}
/** Set the volumen in one layer
* @param int vol Normalized 0 to 1
@param int layer the layer which applied
*/
void AudioMotor::setLayerVolume(int layer, float vol)
{
QString buffer = tr("%1 %2 %3;").arg(layer).arg(VOLUME_COARSE).arg(vol);
if (!sendPacket(buffer.toAscii().constData(), buffer.size()))
{
errorSending();
}
}
/** Set pan in one layer
*
* @param int vol Normalized 0 (Left) to 1 (Right)
@param int layer the layer which applied
*/
void AudioMotor::setLayerPan(int layer, float pan)
{
QString buffer = tr("%1 %2 %3;").arg(layer).arg(PAN).arg(pan);
if (!sendPacket(buffer.toAscii().constData(), buffer.size()))
{
errorSending();
}
}
/** Set Volumen master.
* All layers are limited by this master
* 0 will mute all the outputs
*/
void AudioMotor::setMasterVolume(int vol){
}
/** Set pan master
* Will pan the master output of sound
*/
void AudioMotor::setMasterPan(int pan){
}
/** Restart the audio process
*
*/
void AudioMotor::restartAudio()
{
close();
init();
}
/** New conexion on TCP Server
*
*/
void AudioMotor::newPeer()
{
m_connectedSocket = m_readPD->nextPendingConnection();
connect(m_connectedSocket, SIGNAL(readyRead()),this, SLOT(newMessage()));
}
/** New message in a TCP socket stablished connection
*
*/
void AudioMotor::newMessage()
{
if (m_connectedSocket == NULL)
{
qDebug()<<("AudioMotor::newMessage() Socket not connected. Trying open it...");
emit toTerminal("AudioMotor::newMessage() Socket not connected. Trying open it...");
newPeer();
return;
}
QString message = m_connectedSocket->readAll();
parse(message);
}
void AudioMotor::parse(QString message)
{
QStringList list = message.split("\n", QString::SkipEmptyParts);
for (int i = 0; i < list.size(); i ++) {
if (list.at(i).size() > 0) {
// qDebug() << "AudioMotor::newMessage() message received: " << list.at(i);
QChar val = list.at(i).at(0);
switch (val.digitValue()) {
case 0:
qDebug() << "AudioMotor::newMessage() Loadbang from PD Audio received";
emit toTerminal("AudioMotor::newMessage() Loadbang from PD Audio received");
// Conectamos a Pure Data para escribir
m_writePD->connectToHost(QHostAddress::LocalHost, SOCKET, QIODevice::WriteOnly);
if (m_writePD->waitForConnected(30000))
emit loadbang();
break;
case 9:
if (list.at(i).at(2).digitValue() == 0) {
if (list.at(i).at(7).isDigit() )
emit (volChanged(list.at(i).at(4).digitValue(), ( ( list.at(i).at(6).digitValue() * 10 ) + list.at(i).at(7).digitValue() ) ) );
else
emit (volChanged(list.at(i).at(4).digitValue(), ( ( list.at(i).at(6).digitValue() ) ) ) );
}
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
QStringList folders = list.at(i).split("/", QString::SkipEmptyParts);
if (folders.size() >= 2)
emit (mediaLoaded(val.digitValue(), folders.at(folders.size() -2), folders.at(folders.size() -1)));
break;
}
}
}
}
/** Error writing to PD
*
*/
void AudioMotor::errorWrite(QAbstractSocket::SocketError error)
{
qErrnoWarning(QString("AudioMotor::errorWrite() %1").arg(error).toLatin1());
emit toTerminal(QString("AudioMotor::errorWrite() ") + error);
}
/** Sends packets to Pure Data audio
*
*/
bool AudioMotor::sendPacket(const char *buffer, int bufferLen)
{
if (m_writePD == NULL) {
return false;
}
if (QAbstractSocket::ConnectedState != m_writePD->state())
{
return false;
}
if (bufferLen != m_writePD->write((const char*)buffer, bufferLen))
{
return false;
}
return true;
}
// Function error sending packets to PD audio
void AudioMotor::errorSending() {
qDebug() << "AudioMotor| Can not send packets to PD";
emit toTerminal("AudioMotor| Can not send packets to PD");
}