Merge https://github.com/LMMS/lmms into stable-0.4
This commit is contained in:
200
src/core/VstSyncController.cpp
Normal file
200
src/core/VstSyncController.cpp
Normal 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"
|
||||
|
||||
@@ -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 ) )
|
||||
{
|
||||
|
||||
@@ -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 )
|
||||
|
||||
Reference in New Issue
Block a user