This commit is contained in:
Raine M. Ekman
2014-02-03 22:09:56 +02:00
13 changed files with 403 additions and 354 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -27,7 +27,7 @@
#include "export.h"
#include "MidiEvent.h"
#include "VST_sync_shm.h"
#include "VstSyncData.h"
#include <vector>
#include <cstdio>
@@ -813,7 +813,7 @@ public:
RemotePluginClient( key_t _shm_in, key_t _shm_out );
virtual ~RemotePluginClient();
#ifdef USE_QT_SHMEM
sncVST * getQtVSTshm();
VstSyncData * getQtVSTshm();
#endif
virtual bool processMessage( const message & _m );
@@ -883,7 +883,7 @@ private:
QSharedMemory m_shmObj;
QSharedMemory m_shmQtID;
#endif
sncVST * m_SncVSTplug;
VstSyncData * m_vstSyncData;
float * m_shm;
int m_inputCount;
@@ -1013,7 +1013,7 @@ RemotePluginClient::RemotePluginClient( key_t _shm_in, key_t _shm_out ) :
m_shmObj(),
m_shmQtID( "/usr/bin/lmms" ),
#endif
m_SncVSTplug( NULL ),
m_vstSyncData( NULL ),
m_shm( NULL ),
m_inputCount( 0 ),
m_outputCount( 0 ),
@@ -1023,9 +1023,9 @@ RemotePluginClient::RemotePluginClient( key_t _shm_in, key_t _shm_out ) :
#ifdef USE_QT_SHMEM
if( m_shmQtID.attach( QSharedMemory::ReadOnly ) )
{
m_SncVSTplug = (sncVST *) m_shmQtID.data();
m_bufferSize = m_SncVSTplug->m_bufferSize;
m_sampleRate = m_SncVSTplug->m_sampleRate;
m_vstSyncData = (VstSyncData *) m_shmQtID.data();
m_bufferSize = m_vstSyncData->m_bufferSize;
m_sampleRate = m_vstSyncData->m_sampleRate;
return;
}
#else
@@ -1044,18 +1044,18 @@ RemotePluginClient::RemotePluginClient( key_t _shm_in, key_t _shm_out ) :
}
else
{ // attach segment
m_SncVSTplug = (sncVST *)shmat(m_shmID, 0, 0);
if( m_SncVSTplug == (sncVST *)( -1 ) )
m_vstSyncData = (VstSyncData *)shmat(m_shmID, 0, 0);
if( m_vstSyncData == (VstSyncData *)( -1 ) )
{
perror( "RemotePluginClient::shmat" );
}
else
{
m_bufferSize = m_SncVSTplug->m_bufferSize;
m_sampleRate = m_SncVSTplug->m_sampleRate;
m_bufferSize = m_vstSyncData->m_bufferSize;
m_sampleRate = m_vstSyncData->m_sampleRate;
// detach segment
if( shmdt(m_SncVSTplug) == -1 )
if( shmdt(m_vstSyncData) == -1 )
{
perror("RemotePluginClient::shmdt");
}
@@ -1087,9 +1087,9 @@ RemotePluginClient::~RemotePluginClient()
#ifdef USE_QT_SHMEM
sncVST * RemotePluginClient::getQtVSTshm()
VstSyncData * RemotePluginClient::getQtVSTshm()
{
return m_SncVSTplug;
return m_vstSyncData;
}
#endif

View File

@@ -0,0 +1,99 @@
/*
* VstSyncController.h - type declarations needed for VST to lmms host sync
*
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2013 Mike Choi <rdavidian71/at/gmail/dot/com>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef VST_SYNC_CONTROLLER_H
#define VST_SYNC_CONTROLLER_H
#include <QtCore/QObject>
#include <QtCore/QSharedMemory>
#include "VstSyncData.h"
class VstSyncController : public QObject
{
Q_OBJECT
public:
VstSyncController();
~VstSyncController();
void setAbsolutePosition( int ticks );
void setPlaybackState( bool enabled )
{
m_syncData->isPlaying = enabled;
}
void setTempo( int newTempo );
void setTimeSignature( int num, int denom )
{
m_syncData->timeSigNumer = num;
m_syncData->timeSigDenom = denom;
}
void startCycle( int startTick, int endTick );
void stopCycle()
{
m_syncData->isCycle = false;
}
void update();
private slots:
void updateSampleRate();
private:
struct VstSyncData
{
bool isPlaying;
float ppqPos;
int timeSigNumer;
int timeSigDenom;
bool isCycle;
bool hasSHM;
float cycleStart;
float cycleEnd;
int m_bufferSize;
int m_sampleRate;
int m_bpm;
#ifdef VST_SNC_LATENCY
float m_latency;
#endif
} ;
VstSyncData* m_syncData;
int m_shmID;
QSharedMemory m_shm;
};
#endif

View File

@@ -1,8 +1,9 @@
/*
* VST_sync_shm.h - type declarations needed for VST to lmms host sync
* VstSyncData.h - type declarations needed for VST to lmms host sync
*
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2013 Mike Choi <rdavidian71/at/gmail/dot/com>
*
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
@@ -22,8 +23,8 @@
*
*/
#ifndef _VST_SYNC_SHM_H
#define _VST_SYNC_SHM_H
#ifndef VST_SYNC_DATA_H
#define VST_SYNC_DATA_H
// VST sync frequency (in ms), how often will be VST plugin synced
// keep it power of two if possible (not used by now)
@@ -36,9 +37,11 @@
#define VST_SNC_SHM_KEY_FILE "/dev/null"
//#define VST_SNC_SHM_RND_KEY 3561653564469
struct sncVST
struct VstSyncData
{
bool isPlayin;
bool isPlaying;
float ppqPos;
int timeSigNumer;
int timeSigDenom;

View File

@@ -32,7 +32,7 @@
#include "AutomatableModel.h"
#include "Controller.h"
#include "MeterModel.h"
#include "VST_sync_shm.h"
#include "VstSyncController.h"
class AutomationTrack;
class pattern;
@@ -296,8 +296,6 @@ private slots:
void updateFramesPerTick();
void updateSampleRateSHM();
private:
@@ -356,21 +354,8 @@ private:
tick_t m_elapsedTicks;
tact_t m_elapsedTacts;
enum Actions
{
ActionStop,
ActionPlaySong,
ActionPlayTrack,
ActionPlayBB,
ActionPlayPattern,
ActionPause,
ActionResumeFromPause
} ;
QVector<Actions> m_actions;
VstSyncController m_vstSyncController;
int m_shmID;
sncVST * m_SncVSTplug;
QSharedMemory m_shmQtID;
friend class engine;
friend class songEditor;

View File

@@ -92,7 +92,7 @@ struct ERect
#include "Midi.h"
#include "communication.h"
#include "VST_sync_shm.h"
#include "VstSyncData.h"
#ifdef LMMS_BUILD_WIN32
#define USE_QT_SHMEM
@@ -325,7 +325,7 @@ private:
in * m_in;
int m_shmID;
sncVST * m_SncVSTplug;
VstSyncData* m_vstSyncData;
} ;
@@ -351,7 +351,7 @@ RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) :
m_currentProgram( -1 ),
m_in( NULL ),
m_shmID( -1 ),
m_SncVSTplug( NULL )
m_vstSyncData( NULL )
{
pthread_mutex_init( &m_pluginLock, NULL );
@@ -372,29 +372,29 @@ RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) :
}
else
{ // attach segment
m_SncVSTplug = (sncVST *)shmat(m_shmID, 0, 0);
if( m_SncVSTplug == (sncVST *)( -1 ) )
m_vstSyncData = (VstSyncData *)shmat(m_shmID, 0, 0);
if( m_vstSyncData == (VstSyncData *)( -1 ) )
{
perror( "RemoteVstPlugin.cpp::shmat" );
}
}
}
#else
m_SncVSTplug = RemotePluginClient::getQtVSTshm();
m_vstSyncData = RemotePluginClient::getQtVSTshm();
#endif
if( m_SncVSTplug == NULL )
if( m_vstSyncData == NULL )
{
fprintf(stderr, "RemoteVstPlugin.cpp: "
"Failed to initialize shared memory for VST synchronization.\n"
" (VST-host synchronization will be disabled)\n");
m_SncVSTplug = (sncVST*) malloc( sizeof( sncVST ) );
m_SncVSTplug->isPlayin = true;
m_SncVSTplug->timeSigNumer = 4;
m_SncVSTplug->timeSigDenom = 4;
m_SncVSTplug->ppqPos = 0;
m_SncVSTplug->isCycle = false;
m_SncVSTplug->hasSHM = false;
m_SncVSTplug->m_sampleRate = sampleRate();
m_vstSyncData = (VstSyncData*) malloc( sizeof( VstSyncData ) );
m_vstSyncData->isPlaying = true;
m_vstSyncData->timeSigNumer = 4;
m_vstSyncData->timeSigDenom = 4;
m_vstSyncData->ppqPos = 0;
m_vstSyncData->isCycle = false;
m_vstSyncData->hasSHM = false;
m_vstSyncData->m_sampleRate = sampleRate();
}
m_in = ( in* ) new char[ sizeof( in ) ];
@@ -420,16 +420,16 @@ RemoteVstPlugin::~RemoteVstPlugin()
{
#ifndef USE_QT_SHMEM
// detach shared memory segment
if( shmdt( m_SncVSTplug ) == -1)
if( shmdt( m_vstSyncData ) == -1)
{
if( __plugin->m_SncVSTplug->hasSHM )
if( __plugin->m_vstSyncData->hasSHM )
{
perror( "~RemoteVstPlugin::shmdt" );
}
if( m_SncVSTplug != NULL )
if( m_vstSyncData != NULL )
{
delete m_SncVSTplug;
m_SncVSTplug = NULL;
delete m_vstSyncData;
m_vstSyncData = NULL;
}
}
#endif
@@ -573,7 +573,7 @@ void RemoteVstPlugin::init( const std::string & _plugin_file )
updateInOutCount();
// some plugins have to set samplerate during init
if( m_SncVSTplug->hasSHM )
if( m_vstSyncData->hasSHM )
{
updateSampleRate();
}
@@ -1444,58 +1444,58 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode,
// items may require extensive conversions
// Shared memory was initialised? - see song.cpp
//assert( __plugin->m_SncVSTplug != NULL );
//assert( __plugin->m_vstSyncData != NULL );
memset( &_timeInfo, 0, sizeof( _timeInfo ) );
_timeInfo.samplePos = __plugin->m_currentSamplePos;
_timeInfo.sampleRate = __plugin->m_SncVSTplug->hasSHM ?
__plugin->m_SncVSTplug->m_sampleRate :
_timeInfo.sampleRate = __plugin->m_vstSyncData->hasSHM ?
__plugin->m_vstSyncData->m_sampleRate :
__plugin->sampleRate();
_timeInfo.flags = 0;
_timeInfo.tempo = __plugin->m_SncVSTplug->hasSHM ?
__plugin->m_SncVSTplug->m_bpm :
_timeInfo.tempo = __plugin->m_vstSyncData->hasSHM ?
__plugin->m_vstSyncData->m_bpm :
__plugin->m_bpm;
_timeInfo.timeSigNumerator = __plugin->m_SncVSTplug->timeSigNumer;
_timeInfo.timeSigDenominator = __plugin->m_SncVSTplug->timeSigDenom;
_timeInfo.timeSigNumerator = __plugin->m_vstSyncData->timeSigNumer;
_timeInfo.timeSigDenominator = __plugin->m_vstSyncData->timeSigDenom;
_timeInfo.flags |= kVstTempoValid;
_timeInfo.flags |= kVstTimeSigValid;
if( __plugin->m_SncVSTplug->isCycle )
if( __plugin->m_vstSyncData->isCycle )
{
_timeInfo.cycleStartPos = __plugin->m_SncVSTplug->cycleStart;
_timeInfo.cycleEndPos = __plugin->m_SncVSTplug->cycleEnd;
_timeInfo.cycleStartPos = __plugin->m_vstSyncData->cycleStart;
_timeInfo.cycleEndPos = __plugin->m_vstSyncData->cycleEnd;
_timeInfo.flags |= kVstCyclePosValid;
_timeInfo.flags |= kVstTransportCycleActive;
}
if( __plugin->m_SncVSTplug->ppqPos !=
if( __plugin->m_vstSyncData->ppqPos !=
__plugin->m_in->m_Timestamp )
{
_timeInfo.ppqPos = __plugin->m_SncVSTplug->ppqPos;
_timeInfo.ppqPos = __plugin->m_vstSyncData->ppqPos;
_timeInfo.flags |= kVstTransportChanged;
__plugin->m_in->lastppqPos = __plugin->m_SncVSTplug->ppqPos;
__plugin->m_in->m_Timestamp = __plugin->m_SncVSTplug->ppqPos;
__plugin->m_in->lastppqPos = __plugin->m_vstSyncData->ppqPos;
__plugin->m_in->m_Timestamp = __plugin->m_vstSyncData->ppqPos;
}
else if( __plugin->m_SncVSTplug->isPlayin )
else if( __plugin->m_vstSyncData->isPlaying )
{
__plugin->m_in->lastppqPos += (
__plugin->m_SncVSTplug->hasSHM ?
__plugin->m_SncVSTplug->m_bpm :
__plugin->m_vstSyncData->hasSHM ?
__plugin->m_vstSyncData->m_bpm :
__plugin->m_bpm ) / (float)10340;
_timeInfo.ppqPos = __plugin->m_in->lastppqPos;
}
// _timeInfo.ppqPos = __plugin->m_SncVSTplug->ppqPos;
// _timeInfo.ppqPos = __plugin->m_vstSyncData->ppqPos;
_timeInfo.flags |= kVstPpqPosValid;
if( __plugin->m_SncVSTplug->isPlayin )
if( __plugin->m_vstSyncData->isPlaying )
{
_timeInfo.flags |= kVstTransportPlaying;
}
_timeInfo.barStartPos = ( (int) ( _timeInfo.ppqPos /
( 4 *__plugin->m_SncVSTplug->timeSigNumer
/ (float) __plugin->m_SncVSTplug->timeSigDenom ) ) ) *
( 4 * __plugin->m_SncVSTplug->timeSigNumer
/ (float) __plugin->m_SncVSTplug->timeSigDenom );
( 4 *__plugin->m_vstSyncData->timeSigNumer
/ (float) __plugin->m_vstSyncData->timeSigDenom ) ) ) *
( 4 * __plugin->m_vstSyncData->timeSigNumer
/ (float) __plugin->m_vstSyncData->timeSigDenom );
_timeInfo.flags |= kVstBarsValid;

View File

@@ -0,0 +1,200 @@
/*
* VstSyncController.cpp - manage synchronization between LMMS and VST plugins
*
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2013 Mike Choi <rdavidian71/at/gmail/dot/com>
*
* This file is part of LMMS - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include <QtCore/QDebug>
#include "config_mgr.h"
#include "engine.h"
#include "lmmsconfig.h"
#include "Mixer.h"
#include "VstSyncController.h"
#ifdef LMMS_BUILD_WIN32
#ifndef USE_QT_SHMEM
#define USE_QT_SHMEM
#endif
#endif
#ifndef USE_QT_SHMEM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
VstSyncController::VstSyncController() :
m_syncData( NULL ),
m_shmID( -1 ),
m_shm( "/usr/bin/lmms" )
{
if( configManager::inst()->value( "ui", "syncvstplugins" ).toInt() )
{
connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleRate() ) );
#ifdef USE_QT_SHMEM
if ( m_shm.create( sizeof( VstSyncData ) ) )
{
m_syncData = (VstSyncData*) m_shm.data();
}
else
{
qWarning() << QString( "Failed to allocate shared memory for VST sync: %1" ).arg( m_shm.errorString() );
}
#else
key_t key; // make the key:
if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 )
{
qWarning( "VstSyncController: ftok() failed" );
}
else
{ // connect to shared memory segment
if( ( m_shmID = shmget( key, sizeof( VstSyncData ), 0644 | IPC_CREAT ) ) == -1 )
{
qWarning( "VstSyncController: shmget() failed" );
}
else
{ // attach segment
m_syncData = (VstSyncData *)shmat( m_shmID, 0, 0 );
if( m_syncData == (VstSyncData *)( -1 ) )
{
qWarning( "VstSyncController: shmat() failed" );
}
}
}
#endif
}
else
{
qWarning( "VST sync support disabled in your configuration" );
}
if( m_syncData == NULL )
{
m_syncData = new VstSyncData;
m_syncData->hasSHM = false;
}
else
{
m_syncData->hasSHM = true;
}
m_syncData->isPlaying = false;
m_syncData->m_bufferSize = engine::mixer()->framesPerPeriod();
m_syncData->timeSigNumer = 4;
m_syncData->timeSigDenom = 4;
updateSampleRate();
}
VstSyncController::~VstSyncController()
{
if( m_syncData->hasSHM == false )
{
delete m_syncData;
}
else
{
#ifdef USE_QT_SHMEM
if( m_shm.data() )
{
// detach shared memory, delete it:
m_shm.detach();
}
#else
if( shmdt( m_syncData ) != -1 )
{
shmctl( m_shmID, IPC_RMID, NULL );
}
else
{
qWarning( "VstSyncController: shmdt() failed" );
}
#endif
}
}
void VstSyncController::setAbsolutePosition( int ticks )
{
#ifdef VST_SNC_LATENCY
m_syncData->ppqPos = ( ( ticks + 0 ) / (float)48 ) - m_syncData->m_latency;
#else
m_syncData->ppqPos = ( ( ticks + 0 ) / (float)48 );
#endif
}
void VstSyncController::setTempo( int newTempo )
{
m_syncData->m_bpm = newTempo;
#ifdef VST_SNC_LATENCY
m_syncData->m_latency = m_syncData->m_bufferSize * newTempo / ( (float) m_syncData->m_sampleRate * 60 );
#endif
}
void VstSyncController::startCycle( int startTick, int endTick )
{
m_syncData->isCycle = true;
m_syncData->cycleStart = startTick / (float)48;
m_syncData->cycleEnd = endTick / (float)48;
}
void VstSyncController::update()
{
m_syncData->m_bufferSize = engine::mixer()->framesPerPeriod();
#ifdef VST_SNC_LATENCY
m_syncData->m_latency = m_syncData->m_bufferSize * m_syncData->m_bpm / ( (float) m_syncData->m_sampleRate * 60 );
#endif
}
void VstSyncController::updateSampleRate()
{
m_syncData->m_sampleRate = engine::mixer()->processingSampleRate();
#ifdef VST_SNC_LATENCY
m_syncData->m_latency = m_syncData->m_bufferSize * m_syncData->m_bpm / ( (float) m_syncData->m_sampleRate * 60 );
#endif
}
#include "moc_VstSyncController.cxx"

View File

@@ -123,7 +123,6 @@ void MidiPort::processInEvent( const MidiEvent& event, const MidiTime& time )
event.type() == MidiNoteOff ||
event.type() == MidiKeyPressure )
{
inEvent.setKey( inEvent.key() + KeysPerOctave );
if( inEvent.key() < 0 || inEvent.key() >= NumKeys )
{
return;
@@ -149,14 +148,6 @@ void MidiPort::processOutEvent( const MidiEvent& event, const MidiTime& time )
{
MidiEvent outEvent = event;
if( ( event.type() == MidiNoteOn || event.type() == MidiNoteOff ) &&
fixedOutputNote() >= 0 )
{
// Convert MIDI note number (from spinbox) -> LMMS note number
// that will be converted back when outputted.
outEvent.setKey( fixedOutputNote() - KeysPerOctave );
}
if( fixedOutputVelocity() >= 0 && event.velocity() > 0 &&
( event.type() == MidiNoteOn || event.type() == MidiKeyPressure ) )
{

View File

@@ -63,20 +63,6 @@
#include "timeline.h"
#include "PeakController.h"
#ifdef LMMS_BUILD_WIN32
#ifndef USE_QT_SHMEM
#define USE_QT_SHMEM
#endif
#endif
#ifndef USE_QT_SHMEM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
tick_t MidiTime::s_ticksPerTact = DefaultTicksPerTact;
@@ -108,10 +94,7 @@ song::song() :
m_loopPattern( false ),
m_elapsedMilliSeconds( 0 ),
m_elapsedTicks( 0 ),
m_elapsedTacts( 0 ),
m_shmID( -1 ),
m_SncVSTplug( NULL ),
m_shmQtID( "/usr/bin/lmms" )
m_elapsedTacts( 0 )
{
connect( &m_tempoModel, SIGNAL( dataChanged() ),
this, SLOT( setTempo() ) );
@@ -124,60 +107,6 @@ song::song() :
connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this,
SLOT( updateFramesPerTick() ) );
// handle VST plugins sync
if( configManager::inst()->value( "ui", "syncvstplugins" ).toInt() )
{
connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this,
SLOT( updateSampleRateSHM() ) );
#ifdef USE_QT_SHMEM
if ( !m_shmQtID.create( sizeof( sncVST ) ) )
{
fprintf(stderr, "song.cpp::m_shmQtID create SHM error: %s\n",
m_shmQtID.errorString().toStdString().c_str() );
}
m_SncVSTplug = (sncVST *) m_shmQtID.data();
#else
key_t key; // make the key:
if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 )
{
perror( "song.cpp::ftok" );
}
else
{ // connect to shared memory segment
if( ( m_shmID = shmget( key, sizeof( sncVST ),
0644 | IPC_CREAT ) ) == -1 )
{
perror( "song.cpp::shmget" );
}
else
{ // attach segment
m_SncVSTplug = (sncVST *)shmat(m_shmID, 0, 0);
if( m_SncVSTplug == (sncVST *)( -1 ) )
{
perror( "song.cpp::shmat" );
}
}
}
#endif
// if we are connected into shared memory
if( m_SncVSTplug != NULL )
{
m_SncVSTplug->isPlayin = m_playing | m_exporting;
m_SncVSTplug->hasSHM = true;
m_SncVSTplug->m_sampleRate =
engine::mixer()->processingSampleRate();
m_SncVSTplug->m_bufferSize =
engine::mixer()->framesPerPeriod();
m_SncVSTplug->timeSigNumer = 4;
m_SncVSTplug->timeSigDenom = 4;
}
} // end of VST plugin sync section
if( m_SncVSTplug == NULL )
{
m_SncVSTplug = (sncVST*) malloc( sizeof( sncVST ) );
}
connect( &m_masterVolumeModel, SIGNAL( dataChanged() ),
this, SLOT( masterVolumeChanged() ) );
/* connect( &m_masterPitchModel, SIGNAL( dataChanged() ),
@@ -191,24 +120,6 @@ song::song() :
song::~song()
{
// detach shared memory, delete it:
#ifdef USE_QT_SHMEM
m_shmQtID.detach();
#else
if( shmdt( m_SncVSTplug ) == -1)
{
if( m_SncVSTplug->hasSHM )
{
perror("~song::shmdt");
}
if( m_SncVSTplug != NULL )
{
free( m_SncVSTplug );
m_SncVSTplug = NULL;
}
}
shmctl(m_shmID, IPC_RMID, NULL);
#endif
m_playing = false;
delete m_globalAutomationTrack;
}
@@ -243,12 +154,7 @@ void song::setTempo()
engine::updateFramesPerTick();
m_SncVSTplug->m_bpm = tempo;
#ifdef VST_SNC_LATENCY
m_SncVSTplug->m_latency = m_SncVSTplug->m_bufferSize * tempo /
( (float) m_SncVSTplug->m_sampleRate * 60 );
#endif
m_vstSyncController.setTempo( tempo );
emit tempoChanged( tempo );
}
@@ -262,8 +168,8 @@ void song::setTimeSignature()
emit timeSignatureChanged( m_oldTicksPerTact, ticksPerTact() );
emit dataChanged();
m_oldTicksPerTact = ticksPerTact();
m_SncVSTplug->timeSigNumer = getTimeSigModel().getNumerator();
m_SncVSTplug->timeSigDenom = getTimeSigModel().getDenominator();
m_vstSyncController.setTimeSignature( getTimeSigModel().getNumerator(), getTimeSigModel().getDenominator() );
}
@@ -273,118 +179,6 @@ void song::savePos()
{
timeLine * tl = m_playPos[m_playMode].m_timeLine;
while( !m_actions.empty() )
{
switch( m_actions.front() )
{
case ActionStop:
{
m_playing = false;
m_SncVSTplug->isPlayin = m_exporting;
m_recording = true;
if( tl != NULL )
{
switch( tl->behaviourAtStop() )
{
case timeLine::BackToZero:
m_playPos[m_playMode].setTicks( 0 );
m_elapsedMilliSeconds = 0;
break;
case timeLine::BackToStart:
if( tl->savedPos() >= 0 )
{
m_playPos[m_playMode].setTicks(
tl->savedPos().getTicks() );
m_elapsedMilliSeconds = (((tl->savedPos().getTicks())*60*1000/48)/getTempo());
tl->savePos( -1 );
}
break;
case timeLine::KeepStopPosition:
default:
break;
}
}
else
{
m_playPos[m_playMode].setTicks( 0 );
m_elapsedMilliSeconds = 0;
}
m_playPos[m_playMode].setCurrentFrame( 0 );
// remove all note-play-handles that are active
engine::mixer()->clear();
break;
}
case ActionPlaySong:
m_playMode = Mode_PlaySong;
m_playing = true;
m_SncVSTplug->isPlayin = true;
Controller::resetFrameCounter();
break;
case ActionPlayTrack:
m_playMode = Mode_PlayTrack;
m_playing = true;
m_SncVSTplug->isPlayin = true;
break;
case ActionPlayBB:
m_playMode = Mode_PlayBB;
m_playing = true;
m_SncVSTplug->isPlayin = true;
break;
case ActionPlayPattern:
m_playMode = Mode_PlayPattern;
m_playing = true;
m_SncVSTplug->isPlayin = true;
break;
case ActionPause:
m_playing = false;// just set the play-flag
m_SncVSTplug->isPlayin = m_exporting;
m_paused = true;
break;
case ActionResumeFromPause:
m_playing = true;// just set the play-flag
m_SncVSTplug->isPlayin = true;
m_paused = false;
break;
}
// a second switch for saving pos when starting to play
// anything (need pos for restoring it later in certain
// timeline-modes)
switch( m_actions.front() )
{
case ActionPlaySong:
case ActionPlayTrack:
case ActionPlayBB:
case ActionPlayPattern:
{
if( tl != NULL )
{
tl->savePos( m_playPos[m_playMode] );
}
break;
}
// keep GCC happy...
default:
break;
}
m_actions.erase( m_actions.begin() );
}
if( tl != NULL )
{
tl->savePos( m_playPos[m_playMode] );
@@ -472,28 +266,17 @@ void song::processNextBuffer()
while( total_frames_played
< engine::mixer()->framesPerPeriod() )
{
f_cnt_t played_frames = ( m_SncVSTplug->m_bufferSize = engine::mixer()
->framesPerPeriod() ) - total_frames_played;
m_vstSyncController.update();
#ifdef VST_SNC_LATENCY
m_SncVSTplug->m_latency = m_SncVSTplug->m_bufferSize *
m_SncVSTplug->m_bpm /
( (float) m_SncVSTplug->m_sampleRate * 60 );
#endif
f_cnt_t played_frames = engine::mixer()->framesPerPeriod() - total_frames_played;
float current_frame = m_playPos[m_playMode].currentFrame();
// did we play a tick?
if( current_frame >= frames_per_tick )
{
int ticks = m_playPos[m_playMode].getTicks()
+ (int)( current_frame / frames_per_tick );
int ticks = m_playPos[m_playMode].getTicks() + (int)( current_frame / frames_per_tick );
#ifdef VST_SNC_LATENCY
m_SncVSTplug->ppqPos = ( ( ticks + 0 ) / (float)48 ) -
m_SncVSTplug->m_latency;
#else
m_SncVSTplug->ppqPos = ( ( ticks + 0 ) / (float)48 );
#endif
m_vstSyncController.setAbsolutePosition( ticks );
// did we play a whole tact?
if( ticks >= MidiTime::ticksPerTact() )
@@ -526,39 +309,26 @@ void song::processNextBuffer()
{
// then start from beginning and keep
// offset
ticks = ticks % ( max_tact *
MidiTime::ticksPerTact() );
#ifdef VST_SNC_LATENCY
m_SncVSTplug->ppqPos = ( ( ticks + 0 )
/ (float)48 )
- m_SncVSTplug->m_latency;
#else
m_SncVSTplug->ppqPos = ( ( ticks + 0 )
/ (float)48 );
#endif
ticks = ticks % ( max_tact * MidiTime::ticksPerTact() );
m_vstSyncController.setAbsolutePosition( ticks );
}
}
m_playPos[m_playMode].setTicks( ticks );
if( check_loop )
{
m_SncVSTplug->isCycle = true;
m_SncVSTplug->cycleStart =
( tl->loopBegin().getTicks() )
/ (float)48;
m_SncVSTplug->cycleEnd =
( tl->loopEnd().getTicks() )
/ (float)48;
m_vstSyncController.startCycle( tl->loopBegin().getTicks(), tl->loopEnd().getTicks() );
if( m_playPos[m_playMode] >= tl->loopEnd() )
{
m_playPos[m_playMode].setTicks(
tl->loopBegin().getTicks() );
m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() );
m_elapsedMilliSeconds = ((tl->loopBegin().getTicks())*60*1000/48)/getTempo();
}
}
else
{
m_SncVSTplug->isCycle = false;
m_vstSyncController.stopCycle();
}
current_frame = fmodf( current_frame, frames_per_tick );
@@ -650,8 +420,12 @@ void song::playSong()
m_playing = true;
m_paused = false;
m_vstSyncController.setPlaybackState( true );
savePos();
if(QApplication::type() != QApplication::Tty) {
if( QApplication::type() != QApplication::Tty )
{
engine::updatePlayPauseIcons();
}
}
@@ -689,6 +463,8 @@ void song::playTrack( track * _trackToPlay )
m_playing = true;
m_paused = false;
m_vstSyncController.setPlaybackState( true );
savePos();
engine::updatePlayPauseIcons();
@@ -708,6 +484,8 @@ void song::playBB()
m_playing = true;
m_paused = false;
m_vstSyncController.setPlaybackState( true );
savePos();
engine::updatePlayPauseIcons();
@@ -786,6 +564,8 @@ void song::togglePause()
m_paused = true;
}
m_vstSyncController.setPlaybackState( m_playing );
engine::updatePlayPauseIcons();
}
@@ -812,8 +592,7 @@ void song::stop()
case timeLine::BackToStart:
if( tl->savedPos() >= 0 )
{
m_playPos[m_playMode].setTicks(
tl->savedPos().getTicks() );
m_playPos[m_playMode].setTicks( tl->savedPos().getTicks() );
m_elapsedMilliSeconds = (((tl->savedPos().getTicks())*60*1000/48)/getTempo());
tl->savePos( -1 );
}
@@ -832,6 +611,9 @@ void song::stop()
m_playPos[m_playMode].setCurrentFrame( 0 );
m_vstSyncController.setPlaybackState( m_exporting );
m_vstSyncController.setAbsolutePosition( m_playPos[m_playMode].getTicks() );
// remove all note-play-handles that are active
engine::mixer()->clear();
@@ -852,7 +634,8 @@ void song::startExport()
playSong();
m_exporting = true;
m_SncVSTplug->isPlayin = true;
m_vstSyncController.setPlaybackState( true );
}
@@ -863,7 +646,8 @@ void song::stopExport()
stop();
m_exporting = false;
m_exportLoop = false;
m_SncVSTplug->isPlayin = m_playing;
m_vstSyncController.setPlaybackState( m_playing );
}
@@ -1453,19 +1237,6 @@ void song::updateFramesPerTick()
void song::updateSampleRateSHM()
{
m_SncVSTplug->m_sampleRate = engine::mixer()->processingSampleRate();
#ifdef VST_SNC_LATENCY
m_SncVSTplug->m_latency = m_SncVSTplug->m_bufferSize * m_SncVSTplug->m_bpm /
( (float) m_SncVSTplug->m_sampleRate * 60 );
#endif
}
void song::setModified()
{
if( !m_loadingProject )