378 lines
9.3 KiB
C++
378 lines
9.3 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)
|
|
emit (volChanged(list.at(i).at(4).digitValue(), ( ( list.at(i).at(6).digitValue() * 10 ) + list.at(i).at(7).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)
|
|
{
|
|
// QString error = m_writePD->errorString();
|
|
|
|
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");
|
|
}
|
|
|