Merge branch 'master' into fix/msvc
# Conflicts: # plugins/LadspaEffect/CMakeLists.txt # plugins/Xpressive/Xpressive.cpp # plugins/opl2/CMakeLists.txt # plugins/papu/CMakeLists.txt # plugins/xpressive/CMakeLists.txt # src/CMakeLists.txt
This commit is contained in:
5
src/3rdparty/CMakeLists.txt
vendored
Normal file
5
src/3rdparty/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
set(CMAKE_C_FLAGS "")
|
||||
set(CMAKE_CXX_FLAGS "")
|
||||
|
||||
ADD_SUBDIRECTORY(rpmalloc)
|
||||
ADD_SUBDIRECTORY(weakjack)
|
||||
30
src/3rdparty/rpmalloc/CMakeLists.txt
vendored
Normal file
30
src/3rdparty/rpmalloc/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
set(CMAKE_C_FLAGS "-std=c11")
|
||||
|
||||
add_library(rpmalloc STATIC
|
||||
rpmalloc/rpmalloc/rpmalloc.c
|
||||
rpmalloc/rpmalloc/rpmalloc.h
|
||||
)
|
||||
|
||||
target_include_directories(rpmalloc PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc
|
||||
)
|
||||
|
||||
if (NOT LMMS_BUILD_WIN32)
|
||||
target_compile_definitions(rpmalloc
|
||||
PRIVATE -D_GNU_SOURCE
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_compile_definitions(rpmalloc
|
||||
PRIVATE -DENABLE_ASSERTS=1 -DENABLE_VALIDATE_ARGS=1
|
||||
)
|
||||
endif()
|
||||
|
||||
option(LMMS_ENABLE_MALLOC_STATS "Enables statistics for rpmalloc" OFF)
|
||||
|
||||
if (LMMS_ENABLE_MALLOC_STATS)
|
||||
target_compile_definitions(rpmalloc
|
||||
PRIVATE -DENABLE_STATISTICS=1
|
||||
)
|
||||
endif()
|
||||
1
src/3rdparty/rpmalloc/rpmalloc
vendored
Submodule
1
src/3rdparty/rpmalloc/rpmalloc
vendored
Submodule
Submodule src/3rdparty/rpmalloc/rpmalloc added at 2e0479192b
12
src/3rdparty/weakjack/CMakeLists.txt
vendored
Normal file
12
src/3rdparty/weakjack/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# Use weak jack library linking
|
||||
IF(LMMS_HAVE_WEAKJACK)
|
||||
SET(CMAKE_C_FLAGS "-std=c11")
|
||||
|
||||
# Enable weakjack, disable metadata support
|
||||
ADD_DEFINITIONS(-DUSE_WEAK_JACK=1 -DNO_JACK_METADATA=1)
|
||||
|
||||
# Library stub for AppImages running on systems without jack
|
||||
ADD_LIBRARY(weakjack MODULE weakjack/weak_libjack.c weakjack/weak_libjack.h)
|
||||
TARGET_INCLUDE_DIRECTORIES(weakjack PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/weakjack)
|
||||
INSTALL(TARGETS weakjack LIBRARY DESTINATION "${PLUGIN_DIR}/optional")
|
||||
ENDIF()
|
||||
1
src/3rdparty/weakjack/weakjack
vendored
Submodule
1
src/3rdparty/weakjack/weakjack
vendored
Submodule
Submodule src/3rdparty/weakjack/weakjack added at bffe90c8b1
@@ -1,3 +1,5 @@
|
||||
ADD_SUBDIRECTORY(3rdparty)
|
||||
|
||||
CONFIGURE_FILE("lmmsconfig.h.in" "${CMAKE_BINARY_DIR}/lmmsconfig.h")
|
||||
CONFIGURE_FILE("lmmsversion.h.in" "${CMAKE_BINARY_DIR}/lmmsversion.h")
|
||||
|
||||
@@ -7,7 +9,7 @@ SET(LMMS_UIS "")
|
||||
SET(CMAKE_AUTOMOC ON)
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
# Enable C11 & C++11
|
||||
# Enable C++11
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
IF(LMMS_BUILD_APPLE)
|
||||
@@ -67,6 +69,13 @@ ELSEIF(NOT ("${SDL_INCLUDE_DIR}" STREQUAL ""))
|
||||
INCLUDE_DIRECTORIES("${SDL_INCLUDE_DIR}")
|
||||
ENDIF()
|
||||
|
||||
IF(LMMS_HAVE_WEAKJACK)
|
||||
LIST(APPEND LMMS_SRCS "${WEAKJACK_INCLUDE_DIRS}/weak_libjack.c")
|
||||
LIST(APPEND LMMS_INCLUDES "${WEAKJACK_INCLUDE_DIRS}/weak_libjack.h")
|
||||
INCLUDE_DIRECTORIES("${WEAKJACK_INCLUDE_DIRS}")
|
||||
ADD_DEFINITIONS(-DUSE_WEAK_JACK=1 -DNO_JACK_METADATA=1)
|
||||
ENDIF()
|
||||
|
||||
IF(NOT ("${PORTAUDIO_INCLUDE_DIR}" STREQUAL ""))
|
||||
INCLUDE_DIRECTORIES("${PORTAUDIO_INCLUDE_DIR}")
|
||||
ENDIF()
|
||||
@@ -149,7 +158,9 @@ SET(LMMS_REQUIRED_LIBS
|
||||
${SAMPLERATE_LIBRARIES}
|
||||
${SNDFILE_LIBRARIES}
|
||||
${EXTRA_LIBRARIES}
|
||||
rpmalloc
|
||||
)
|
||||
|
||||
# Expose required libs for tests binary
|
||||
SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} PARENT_SCOPE)
|
||||
|
||||
@@ -157,6 +168,16 @@ TARGET_LINK_LIBRARIES(lmms
|
||||
${LMMS_REQUIRED_LIBS}
|
||||
)
|
||||
|
||||
FOREACH(LIB ${LMMS_REQUIRED_LIBS})
|
||||
IF(TARGET ${LIB})
|
||||
GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
IF(INCLUDE_DIRS)
|
||||
TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
|
||||
|
||||
# Required libs for debug msys builds
|
||||
IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
TARGET_LINK_LIBRARIES(lmms QtCore4 QtGui4 QtXml4)
|
||||
|
||||
@@ -503,7 +503,16 @@ void ConfigManager::loadConfigFile( const QString & configFile )
|
||||
#elif defined(LMMS_BUILD_APPLE)
|
||||
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
|
||||
#else
|
||||
m_stkDir = "/usr/share/stk/rawwaves/";
|
||||
if ( qApp->applicationDirPath().startsWith("/tmp/") )
|
||||
{
|
||||
// Assume AppImage bundle
|
||||
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to system provided location
|
||||
m_stkDir = "/usr/share/stk/rawwaves/";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -194,7 +194,7 @@ bool DataFile::validate( QString extension )
|
||||
if (! ( extension == "mmp" || extension == "mpt" || extension == "mmpz" ||
|
||||
extension == "xpf" || extension == "xml" ||
|
||||
( extension == "xiz" && ! pluginFactory->pluginSupportingExtension(extension).isNull()) ||
|
||||
extension == "sf2" || extension == "pat" || extension == "mid" ||
|
||||
extension == "sf2" || extension == "sf3" || extension == "pat" || extension == "mid" ||
|
||||
extension == "dll"
|
||||
) )
|
||||
{
|
||||
@@ -968,6 +968,61 @@ void DataFile::upgrade_1_2_0_rc2_42()
|
||||
}
|
||||
|
||||
|
||||
void DataFile::upgrade_1_3_0()
|
||||
{
|
||||
QDomNodeList list = elementsByTagName( "instrument" );
|
||||
for( int i = 0; !list.item( i ).isNull(); ++i )
|
||||
{
|
||||
QDomElement el = list.item( i ).toElement();
|
||||
if( el.attribute( "name" ) == "papu" )
|
||||
{
|
||||
el.setAttribute( "name", "freeboy" );
|
||||
QDomNodeList children = el.elementsByTagName( "papu" );
|
||||
for( int j = 0; !children.item( j ).isNull(); ++j )
|
||||
{
|
||||
QDomElement child = children.item( j ).toElement();
|
||||
child.setTagName( "freeboy" );
|
||||
}
|
||||
}
|
||||
else if( el.attribute( "name" ) == "OPL2" )
|
||||
{
|
||||
el.setAttribute( "name", "opulenz" );
|
||||
QDomNodeList children = el.elementsByTagName( "OPL2" );
|
||||
for( int j = 0; !children.item( j ).isNull(); ++j )
|
||||
{
|
||||
QDomElement child = children.item( j ).toElement();
|
||||
child.setTagName( "opulenz" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list = elementsByTagName( "effect" );
|
||||
for( int i = 0; !list.item( i ).isNull(); ++i )
|
||||
{
|
||||
QDomElement effect = list.item( i ).toElement();
|
||||
if( effect.attribute( "name" ) == "ladspaeffect" )
|
||||
{
|
||||
QDomNodeList keys = effect.elementsByTagName( "key" );
|
||||
for( int j = 0; !keys.item( j ).isNull(); ++j )
|
||||
{
|
||||
QDomElement key = keys.item( j ).toElement();
|
||||
QDomNodeList attributes = key.elementsByTagName( "attribute" );
|
||||
for( int k = 0; !attributes.item( k ).isNull(); ++k )
|
||||
{
|
||||
QDomElement attribute = attributes.item( k ).toElement();
|
||||
if( attribute.attribute( "name" ) == "file" &&
|
||||
( attribute.attribute( "value" ) == "calf" ||
|
||||
attribute.attribute( "value" ) == "calf.so" ) )
|
||||
{
|
||||
attribute.setAttribute( "value", "veal" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DataFile::upgrade()
|
||||
{
|
||||
ProjectVersion version =
|
||||
@@ -1049,6 +1104,10 @@ void DataFile::upgrade()
|
||||
upgrade_1_2_0_rc3();
|
||||
upgrade_1_2_0_rc2_42();
|
||||
}
|
||||
if( version < "1.3.0" )
|
||||
{
|
||||
upgrade_1_3_0();
|
||||
}
|
||||
|
||||
// update document meta data
|
||||
documentElement().setAttribute( "version", LDF_VERSION_STRING );
|
||||
|
||||
@@ -305,7 +305,7 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) :
|
||||
m_arpCycleModel( 0.0f, 0.0f, 6.0f, 1.0f, this, tr( "Cycle steps" ) ),
|
||||
m_arpSkipModel( 0.0f, 0.0f, 100.0f, 1.0f, this, tr( "Skip rate" ) ),
|
||||
m_arpMissModel( 0.0f, 0.0f, 100.0f, 1.0f, this, tr( "Miss rate" ) ),
|
||||
m_arpTimeModel( 100.0f, 25.0f, 2000.0f, 1.0f, 2000, this, tr( "Arpeggio time" ) ),
|
||||
m_arpTimeModel( 200.0f, 25.0f, 2000.0f, 1.0f, 2000, this, tr( "Arpeggio time" ) ),
|
||||
m_arpGateModel( 100.0f, 1.0f, 200.0f, 1.0f, this, tr( "Arpeggio gate" ) ),
|
||||
m_arpDirectionModel( this, tr( "Arpeggio direction" ) ),
|
||||
m_arpModeModel( this, tr( "Arpeggio mode" ) )
|
||||
@@ -396,14 +396,13 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
|
||||
|
||||
frames_processed += remaining_frames_for_cur_arp;
|
||||
|
||||
// init with zero
|
||||
int cur_arp_idx = 0;
|
||||
|
||||
// in sorted mode: is it our turn or do we have to be quiet for
|
||||
// now?
|
||||
if( m_arpModeModel.value() == SortMode &&
|
||||
( ( cur_frame / arp_frames ) % total_range ) / range != (f_cnt_t) _n->index() )
|
||||
{
|
||||
// Set master note if not playing arp note or it will play as an ordinary note
|
||||
_n->setMasterNote();
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
@@ -416,10 +415,9 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
|
||||
|
||||
if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpSkipModel.value() )
|
||||
{
|
||||
if( cur_arp_idx == 0 )
|
||||
{
|
||||
_n->setMasterNote();
|
||||
}
|
||||
// Set master note to prevent the note to extend over skipped notes
|
||||
// This may only be needed for lb302
|
||||
_n->setMasterNote();
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
@@ -440,6 +438,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
|
||||
}
|
||||
}
|
||||
|
||||
int cur_arp_idx = 0;
|
||||
// process according to arpeggio-direction...
|
||||
if( dir == ArpDirUp )
|
||||
{
|
||||
@@ -525,6 +524,13 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
}
|
||||
|
||||
// make sure note is handled as arp-base-note, even
|
||||
// if we didn't add a sub-note so far
|
||||
if( m_arpModeModel.value() != FreeMode )
|
||||
{
|
||||
_n->setMasterNote();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -300,13 +300,22 @@ f_cnt_t InstrumentSoundShaping::envFrames( const bool _only_vol ) const
|
||||
|
||||
f_cnt_t InstrumentSoundShaping::releaseFrames() const
|
||||
{
|
||||
if( !m_instrumentTrack->instrument() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
f_cnt_t ret_val = m_instrumentTrack->instrument()->desiredReleaseFrames();
|
||||
|
||||
if( m_instrumentTrack->instrument()->flags().testFlag( Instrument::IsSingleStreamed ) )
|
||||
{
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
if( m_envLfoParameters[Volume]->isUsed() )
|
||||
{
|
||||
return m_envLfoParameters[Volume]->releaseFrames();
|
||||
}
|
||||
f_cnt_t ret_val = m_instrumentTrack->instrument()
|
||||
? m_instrumentTrack->instrument()->desiredReleaseFrames()
|
||||
: 0;
|
||||
|
||||
for( int i = Volume+1; i < NumTargets; ++i )
|
||||
{
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*
|
||||
* MemoryManager.cpp - A lightweight, generic memory manager for LMMS
|
||||
* MemoryManager.cpp
|
||||
*
|
||||
* Copyright (c) 2014 Vesa Kivimäki
|
||||
* Copyright (c) 2007-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2017 Lukas W <lukaswhl/at/gmail.com>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -25,197 +24,54 @@
|
||||
|
||||
|
||||
#include "MemoryManager.h"
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include "rpmalloc.h"
|
||||
|
||||
/// Global static object handling rpmalloc intializing and finalizing
|
||||
struct MemoryManagerGlobalGuard {
|
||||
MemoryManagerGlobalGuard() {
|
||||
rpmalloc_initialize();
|
||||
}
|
||||
~MemoryManagerGlobalGuard() {
|
||||
rpmalloc_finalize();
|
||||
}
|
||||
} static mm_global_guard;
|
||||
|
||||
|
||||
MemoryPoolVector MemoryManager::s_memoryPools;
|
||||
QReadWriteLock MemoryManager::s_poolMutex;
|
||||
PointerInfoMap MemoryManager::s_pointerInfo;
|
||||
QMutex MemoryManager::s_pointerMutex;
|
||||
|
||||
|
||||
bool MemoryManager::init()
|
||||
{
|
||||
s_memoryPools.reserve( 64 );
|
||||
s_pointerInfo.reserve( 4096 );
|
||||
// construct first MemoryPool and allocate memory
|
||||
MemoryPool m ( MM_INITIAL_CHUNKS );
|
||||
m.m_pool = MemoryHelper::alignedMalloc( MM_INITIAL_CHUNKS * MM_CHUNK_SIZE );
|
||||
s_memoryPools.append( m );
|
||||
return true;
|
||||
namespace {
|
||||
static thread_local size_t thread_guard_depth;
|
||||
}
|
||||
|
||||
|
||||
void * MemoryManager::alloc( size_t size )
|
||||
MemoryManager::ThreadGuard::ThreadGuard()
|
||||
{
|
||||
if( !size )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int requiredChunks = size / MM_CHUNK_SIZE + ( size % MM_CHUNK_SIZE > 0 ? 1 : 0 );
|
||||
|
||||
MemoryPool * mp = NULL;
|
||||
void * ptr = NULL;
|
||||
|
||||
MemoryPoolVector::iterator it = s_memoryPools.begin();
|
||||
|
||||
s_poolMutex.lockForRead();
|
||||
while( it != s_memoryPools.end() && !ptr )
|
||||
{
|
||||
ptr = ( *it ).getChunks( requiredChunks );
|
||||
if( ptr )
|
||||
{
|
||||
mp = &( *it );
|
||||
}
|
||||
++it;
|
||||
}
|
||||
s_poolMutex.unlock();
|
||||
|
||||
if( ptr )
|
||||
{
|
||||
s_pointerMutex.lock();
|
||||
PtrInfo p;
|
||||
p.chunks = requiredChunks;
|
||||
p.memPool = mp;
|
||||
s_pointerInfo[ptr] = p;
|
||||
s_pointerMutex.unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// can't find enough chunks in existing pools, so
|
||||
// create a new pool that is guaranteed to have enough chunks
|
||||
int moreChunks = qMax( requiredChunks, MM_INCREMENT_CHUNKS );
|
||||
int i = MemoryManager::extend( moreChunks );
|
||||
|
||||
mp = &s_memoryPools[i];
|
||||
ptr = s_memoryPools[i].getChunks( requiredChunks );
|
||||
if( ptr )
|
||||
{
|
||||
s_pointerMutex.lock();
|
||||
PtrInfo p;
|
||||
p.chunks = requiredChunks;
|
||||
p.memPool = mp;
|
||||
s_pointerInfo[ptr] = p;
|
||||
s_pointerMutex.unlock();
|
||||
return ptr;
|
||||
}
|
||||
// still no luck? something is horribly wrong
|
||||
qFatal( "MemoryManager.cpp: Couldn't allocate memory: %d chunks asked", requiredChunks );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void MemoryManager::free( void * ptr )
|
||||
{
|
||||
if( !ptr )
|
||||
{
|
||||
return; // Null pointer deallocations are OK but do not need to be handled
|
||||
}
|
||||
|
||||
// fetch info on the ptr and remove
|
||||
s_pointerMutex.lock();
|
||||
if( ! s_pointerInfo.contains( ptr ) ) // if we have no info on ptr, fail loudly
|
||||
{
|
||||
qFatal( "MemoryManager: Couldn't find pointer info for pointer: %p", ptr );
|
||||
}
|
||||
PtrInfo p = s_pointerInfo[ptr];
|
||||
s_pointerInfo.remove( ptr );
|
||||
s_pointerMutex.unlock();
|
||||
|
||||
p.memPool->releaseChunks( ptr, p.chunks );
|
||||
}
|
||||
|
||||
|
||||
int MemoryManager::extend( int chunks )
|
||||
{
|
||||
MemoryPool m ( chunks );
|
||||
m.m_pool = MemoryHelper::alignedMalloc( chunks * MM_CHUNK_SIZE );
|
||||
|
||||
s_poolMutex.lockForWrite();
|
||||
s_memoryPools.append( m );
|
||||
int i = s_memoryPools.size() - 1;
|
||||
s_poolMutex.unlock();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
void MemoryManager::cleanup()
|
||||
{
|
||||
for( MemoryPoolVector::iterator it = s_memoryPools.begin(); it != s_memoryPools.end(); ++it )
|
||||
{
|
||||
MemoryHelper::alignedFree( ( *it ).m_pool );
|
||||
MemoryHelper::alignedFree( ( *it ).m_free );
|
||||
if (thread_guard_depth++ == 0) {
|
||||
rpmalloc_thread_initialize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void * MemoryPool::getChunks( int chunksNeeded )
|
||||
MemoryManager::ThreadGuard::~ThreadGuard()
|
||||
{
|
||||
if( chunksNeeded > m_chunks ) // not enough chunks in this pool?
|
||||
{
|
||||
return NULL;
|
||||
if (--thread_guard_depth == 0) {
|
||||
rpmalloc_thread_finalize();
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
static thread_local MemoryManager::ThreadGuard local_mm_thread_guard{};
|
||||
|
||||
// now find out if we have a long enough sequence of chunks in this pool
|
||||
char last = 0;
|
||||
intptr_t n = 0;
|
||||
intptr_t index = -1;
|
||||
bool found = false;
|
||||
|
||||
for( int i = 0; i < m_chunks; ++i )
|
||||
{
|
||||
if( m_free[i] )
|
||||
{
|
||||
if( !last )
|
||||
{
|
||||
index = i;
|
||||
}
|
||||
|
||||
++n;
|
||||
if( n >= chunksNeeded )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
|
||||
last = m_free[i];
|
||||
}
|
||||
|
||||
if( found ) // if enough chunks found, return pointer to chunks
|
||||
{
|
||||
// set chunk flags to false so we know the chunks are in use
|
||||
for( intptr_t i = 0; i < chunksNeeded; ++i )
|
||||
{
|
||||
m_free[ index + i ] = 0;
|
||||
}
|
||||
m_mutex.unlock();
|
||||
return (char*)m_pool + ( index * MM_CHUNK_SIZE );
|
||||
}
|
||||
m_mutex.unlock();
|
||||
return NULL; // out of stock, come again tomorrow!
|
||||
void* MemoryManager::alloc(size_t size)
|
||||
{
|
||||
// Reference local thread guard to ensure it is initialized.
|
||||
// Compilers may optimize the instance away otherwise.
|
||||
Q_UNUSED(&local_mm_thread_guard);
|
||||
Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::alloc", "Thread not initialized");
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
|
||||
void MemoryPool::releaseChunks( void * ptr, int chunks )
|
||||
void MemoryManager::free(void * ptr)
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
intptr_t start = ( (intptr_t)ptr - (intptr_t)m_pool ) / MM_CHUNK_SIZE;
|
||||
if( start < 0 )
|
||||
{
|
||||
qFatal( "MemoryManager: error at releaseChunks() - corrupt pointer info?" );
|
||||
}
|
||||
|
||||
memset( &m_free[ start ], 1, chunks );
|
||||
|
||||
m_mutex.unlock();
|
||||
Q_UNUSED(&local_mm_thread_guard);
|
||||
Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::free", "Thread not initialized");
|
||||
return rpfree(ptr);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "NotePlayHandle.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "SamplePlayHandle.h"
|
||||
#include "MemoryHelper.h"
|
||||
|
||||
// platform-specific audio-interface-classes
|
||||
#include "AudioAlsa.h"
|
||||
|
||||
@@ -151,6 +151,7 @@ void MixerWorkerThread::startAndWaitForJobs()
|
||||
|
||||
void MixerWorkerThread::run()
|
||||
{
|
||||
MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard);
|
||||
disable_denormals();
|
||||
|
||||
QMutex m;
|
||||
|
||||
@@ -128,7 +128,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
|
||||
}
|
||||
|
||||
|
||||
void NotePlayHandle::done()
|
||||
NotePlayHandle::~NotePlayHandle()
|
||||
{
|
||||
lock();
|
||||
noteOff( 0 );
|
||||
@@ -599,7 +599,7 @@ NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrac
|
||||
|
||||
void NotePlayHandleManager::release( NotePlayHandle * nph )
|
||||
{
|
||||
nph->done();
|
||||
nph->NotePlayHandle::~NotePlayHandle();
|
||||
s_mutex.lockForRead();
|
||||
s_available[ s_availableIndex.fetchAndAddOrdered( 1 ) + 1 ] = nph;
|
||||
s_mutex.unlock();
|
||||
|
||||
@@ -54,6 +54,7 @@ void PlayHandle::doProcessing()
|
||||
if( m_usesBuffer )
|
||||
{
|
||||
m_bufferReleased = false;
|
||||
BufferManager::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod());
|
||||
play( buffer() );
|
||||
}
|
||||
else
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QAtomicPointer>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "PresetPreviewPlayHandle.h"
|
||||
@@ -66,12 +67,25 @@ public:
|
||||
|
||||
NotePlayHandle* previewNote()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return m_previewNote.loadAcquire();
|
||||
#else
|
||||
return m_previewNote;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setPreviewNote( NotePlayHandle * _note )
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
m_previewNote.storeRelease( _note );
|
||||
#else
|
||||
m_previewNote = _note;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool testAndSetPreviewNote( NotePlayHandle * expectedVal, NotePlayHandle * newVal )
|
||||
{
|
||||
return m_previewNote.testAndSetOrdered( expectedVal, newVal );
|
||||
}
|
||||
|
||||
void lockData()
|
||||
@@ -97,7 +111,7 @@ public:
|
||||
|
||||
private:
|
||||
InstrumentTrack* m_previewInstrumentTrack;
|
||||
NotePlayHandle* m_previewNote;
|
||||
QAtomicPointer<NotePlayHandle> m_previewNote;
|
||||
QMutex m_dataMutex;
|
||||
|
||||
friend class PresetPreviewPlayHandle;
|
||||
@@ -113,15 +127,14 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
|
||||
PlayHandle( TypePresetPreviewHandle ),
|
||||
m_previewNote( NULL )
|
||||
{
|
||||
s_previewTC->lockData();
|
||||
|
||||
setUsesBuffer( false );
|
||||
|
||||
if( s_previewTC->previewNote() != NULL )
|
||||
{
|
||||
s_previewTC->previewNote()->mute();
|
||||
}
|
||||
s_previewTC->lockData();
|
||||
|
||||
Engine::mixer()->requestChangeInModel();
|
||||
s_previewTC->setPreviewNote( nullptr );
|
||||
s_previewTC->previewInstrumentTrack()->silenceAllNotes();
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
|
||||
const bool j = Engine::projectJournal()->isJournalling();
|
||||
Engine::projectJournal()->setJournalling( false );
|
||||
@@ -174,6 +187,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
|
||||
s_previewTC->previewInstrumentTrack()->
|
||||
midiPort()->setMode( MidiPort::Disabled );
|
||||
|
||||
Engine::mixer()->requestChangeInModel();
|
||||
// create note-play-handle for it
|
||||
m_previewNote = NotePlayHandleManager::acquire(
|
||||
s_previewTC->previewInstrumentTrack(), 0,
|
||||
@@ -186,6 +200,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
|
||||
|
||||
Engine::mixer()->addPlayHandle( m_previewNote );
|
||||
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
s_previewTC->unlockData();
|
||||
Engine::projectJournal()->setJournalling( j );
|
||||
}
|
||||
@@ -195,15 +210,13 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
|
||||
|
||||
PresetPreviewPlayHandle::~PresetPreviewPlayHandle()
|
||||
{
|
||||
s_previewTC->lockData();
|
||||
Engine::mixer()->requestChangeInModel();
|
||||
// not muted by other preset-preview-handle?
|
||||
if( !m_previewNote->isMuted() )
|
||||
if (s_previewTC->testAndSetPreviewNote(m_previewNote, nullptr))
|
||||
{
|
||||
// then set according state
|
||||
s_previewTC->setPreviewNote( NULL );
|
||||
m_previewNote->noteOff();
|
||||
}
|
||||
m_previewNote->noteOff();
|
||||
s_previewTC->unlockData();
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +241,7 @@ bool PresetPreviewPlayHandle::isFinished() const
|
||||
|
||||
bool PresetPreviewPlayHandle::isFromTrack( const Track * _track ) const
|
||||
{
|
||||
return s_previewTC->previewInstrumentTrack() == _track;
|
||||
return s_previewTC && s_previewTC->previewInstrumentTrack() == _track;
|
||||
}
|
||||
|
||||
|
||||
@@ -258,13 +271,11 @@ ConstNotePlayHandleList PresetPreviewPlayHandle::nphsOfInstrumentTrack(
|
||||
const InstrumentTrack * _it )
|
||||
{
|
||||
ConstNotePlayHandleList cnphv;
|
||||
s_previewTC->lockData();
|
||||
if( s_previewTC->previewNote() != NULL &&
|
||||
s_previewTC->previewNote()->instrumentTrack() == _it )
|
||||
{
|
||||
cnphv.push_back( s_previewTC->previewNote() );
|
||||
}
|
||||
s_previewTC->unlockData();
|
||||
return cnphv;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,15 +41,15 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
{
|
||||
|
||||
{ ProjectRenderer::WaveFile,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "WAV-File (*.wav)" ),
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "WAV (*.wav)" ),
|
||||
".wav", &AudioFileWave::getInst },
|
||||
{ ProjectRenderer::FlacFile,
|
||||
QT_TRANSLATE_NOOP("ProjectRenderer", "FLAC-File (*.flac)"),
|
||||
QT_TRANSLATE_NOOP("ProjectRenderer", "FLAC (*.flac)"),
|
||||
".flac",
|
||||
&AudioFileFlac::getInst
|
||||
},
|
||||
{ ProjectRenderer::OggFile,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "Compressed OGG-File (*.ogg)" ),
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "OGG (*.ogg)" ),
|
||||
".ogg",
|
||||
#ifdef LMMS_HAVE_OGGVORBIS
|
||||
&AudioFileOgg::getInst
|
||||
@@ -58,7 +58,7 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
#endif
|
||||
},
|
||||
{ ProjectRenderer::MP3File,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "Compressed MP3-File (*.mp3)" ),
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "MP3 (*.mp3)" ),
|
||||
".mp3",
|
||||
#ifdef LMMS_HAVE_MP3LAME
|
||||
&AudioFileMP3::getInst
|
||||
@@ -66,8 +66,8 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
NULL
|
||||
#endif
|
||||
},
|
||||
// ... insert your own file-encoder-infos here... may be one day the
|
||||
// user can add own encoders inside the program...
|
||||
// Insert your own file-encoder infos here.
|
||||
// Maybe one day the user can add own encoders inside the program.
|
||||
|
||||
{ ProjectRenderer::NumFileFormats, NULL, NULL, NULL }
|
||||
|
||||
@@ -109,15 +109,15 @@ ProjectRenderer::ProjectRenderer( const Mixer::qualitySettings & qualitySettings
|
||||
|
||||
ProjectRenderer::~ProjectRenderer()
|
||||
{
|
||||
Engine::mixer()->restoreAudioDevice(); // also deletes audio-dev
|
||||
Engine::mixer()->restoreAudioDevice(); // Also deletes audio dev.
|
||||
Engine::mixer()->changeQuality( m_oldQualitySettings );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// little help-function for getting file-format from a file-extension (only for
|
||||
// registered file-encoders)
|
||||
// Little help function for getting file format from a file extension
|
||||
// (only for registered file-encoders).
|
||||
ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension(
|
||||
const QString & _ext )
|
||||
{
|
||||
@@ -131,7 +131,7 @@ ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension(
|
||||
++idx;
|
||||
}
|
||||
|
||||
return( WaveFile ); // default
|
||||
return( WaveFile ); // Default.
|
||||
}
|
||||
|
||||
|
||||
@@ -151,9 +151,8 @@ void ProjectRenderer::startProcessing()
|
||||
|
||||
if( isReady() )
|
||||
{
|
||||
// have to do mixer stuff with GUI-thread-affinity in order to
|
||||
// make slots connected to sampleRateChanged()-signals being
|
||||
// called immediately
|
||||
// Have to do mixer stuff with GUI-thread affinity in order to
|
||||
// make slots connected to sampleRateChanged()-signals being called immediately.
|
||||
Engine::mixer()->setAudioDevice( m_fileDev,
|
||||
m_qualitySettings, false );
|
||||
|
||||
@@ -169,6 +168,7 @@ void ProjectRenderer::startProcessing()
|
||||
|
||||
void ProjectRenderer::run()
|
||||
{
|
||||
MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard);
|
||||
#if 0
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
#ifdef LMMS_HAVE_SCHED_H
|
||||
@@ -182,7 +182,7 @@ void ProjectRenderer::run()
|
||||
|
||||
Engine::getSong()->startExport();
|
||||
Engine::getSong()->updateLength();
|
||||
//skip first empty buffer
|
||||
// Skip first empty buffer.
|
||||
Engine::mixer()->nextBuffer();
|
||||
|
||||
const Song::PlayPos & exportPos = Engine::getSong()->getPlayPos(
|
||||
@@ -193,7 +193,7 @@ void ProjectRenderer::run()
|
||||
tick_t endTick = exportEndpoints.second.getTicks();
|
||||
tick_t lengthTicks = endTick - startTick;
|
||||
|
||||
// Continually track and emit progress percentage to listeners
|
||||
// Continually track and emit progress percentage to listeners.
|
||||
while( exportPos.getTicks() < endTick &&
|
||||
Engine::getSong()->isExporting() == true
|
||||
&& !m_abort )
|
||||
@@ -207,12 +207,12 @@ void ProjectRenderer::run()
|
||||
}
|
||||
}
|
||||
|
||||
// notify mixer of the end of processing
|
||||
// Notify mixer of the end of processing.
|
||||
Engine::mixer()->stopProcessing();
|
||||
|
||||
Engine::getSong()->stopExport();
|
||||
|
||||
// if the user aborted export-process, the file has to be deleted
|
||||
// If the user aborted export-process, the file has to be deleted.
|
||||
const QString f = m_fileDev->outputFile();
|
||||
if( m_abort )
|
||||
{
|
||||
@@ -255,4 +255,3 @@ void ProjectRenderer::updateConsoleProgress()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -90,10 +90,10 @@ Song::Song() :
|
||||
m_length( 0 ),
|
||||
m_patternToPlay( NULL ),
|
||||
m_loopPattern( false ),
|
||||
m_elapsedMilliSeconds( 0 ),
|
||||
m_elapsedTicks( 0 ),
|
||||
m_elapsedTacts( 0 )
|
||||
{
|
||||
for(int i = 0; i < Mode_Count; ++i) m_elapsedMilliSeconds[i] = 0;
|
||||
connect( &m_tempoModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( setTempo() ) );
|
||||
connect( &m_tempoModel, SIGNAL( dataUnchanged() ),
|
||||
@@ -387,7 +387,7 @@ void Song::processNextBuffer()
|
||||
framesPlayed += framesToPlay;
|
||||
m_playPos[m_playMode].setCurrentFrame( framesToPlay +
|
||||
currentFrame );
|
||||
m_elapsedMilliSeconds += MidiTime::ticksToMilliseconds( framesToPlay / framesPerTick, getTempo());
|
||||
m_elapsedMilliSeconds[m_playMode] += MidiTime::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo());
|
||||
m_elapsedTacts = m_playPos[Mode_PlaySong].getTact();
|
||||
m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerTact() ) / 48;
|
||||
}
|
||||
@@ -597,7 +597,7 @@ void Song::setPlayPos( tick_t ticks, PlayModes playMode )
|
||||
{
|
||||
tick_t ticksFromPlayMode = m_playPos[playMode].getTicks();
|
||||
m_elapsedTicks += ticksFromPlayMode - ticks;
|
||||
m_elapsedMilliSeconds += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() );
|
||||
m_elapsedMilliSeconds[m_playMode] += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() );
|
||||
m_playPos[playMode].setTicks( ticks );
|
||||
m_playPos[playMode].setCurrentFrame( 0.0f );
|
||||
|
||||
@@ -651,8 +651,8 @@ void Song::stop()
|
||||
switch( tl->behaviourAtStop() )
|
||||
{
|
||||
case TimeLineWidget::BackToZero:
|
||||
m_playPos[m_playMode].setTicks( 0 );
|
||||
m_elapsedMilliSeconds = 0;
|
||||
m_playPos[m_playMode].setTicks(0);
|
||||
m_elapsedMilliSeconds[m_playMode] = 0;
|
||||
if( gui && gui->songEditor() &&
|
||||
( tl->autoScroll() == TimeLineWidget::AutoScrollEnabled ) )
|
||||
{
|
||||
@@ -663,7 +663,7 @@ void Song::stop()
|
||||
case TimeLineWidget::BackToStart:
|
||||
if( tl->savedPos() >= 0 )
|
||||
{
|
||||
m_playPos[m_playMode].setTicks( tl->savedPos().getTicks() );
|
||||
m_playPos[m_playMode].setTicks(tl->savedPos().getTicks());
|
||||
setToTime(tl->savedPos());
|
||||
|
||||
if( gui && gui->songEditor() &&
|
||||
@@ -683,10 +683,13 @@ void Song::stop()
|
||||
else
|
||||
{
|
||||
m_playPos[m_playMode].setTicks( 0 );
|
||||
m_elapsedMilliSeconds = 0;
|
||||
m_elapsedMilliSeconds[m_playMode] = 0;
|
||||
}
|
||||
m_playing = false;
|
||||
|
||||
m_elapsedMilliSeconds[Mode_None] = m_elapsedMilliSeconds[m_playMode];
|
||||
m_playPos[Mode_None].setTicks(m_playPos[m_playMode].getTicks());
|
||||
|
||||
m_playPos[m_playMode].setCurrentFrame( 0 );
|
||||
|
||||
m_vstSyncController.setPlaybackState( m_exporting );
|
||||
|
||||
@@ -166,6 +166,9 @@ void TrackContentObject::changeLength( const MidiTime & length )
|
||||
emit lengthChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool TrackContentObject::comparePosition(const TrackContentObject *a, const TrackContentObject *b)
|
||||
{
|
||||
return a->startPosition() < b->startPosition();
|
||||
@@ -224,6 +227,22 @@ void TrackContentObject::toggleMute()
|
||||
|
||||
|
||||
|
||||
MidiTime TrackContentObject::startTimeOffset() const
|
||||
{
|
||||
return m_startTimeOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TrackContentObject::setStartTimeOffset( const MidiTime &startTimeOffset )
|
||||
{
|
||||
m_startTimeOffset = startTimeOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -698,20 +717,10 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
|
||||
}
|
||||
else
|
||||
{
|
||||
gui->songEditor()->m_editor->selectAllTcos( false );
|
||||
QVector<TrackContentObjectView *> tcoViews;
|
||||
tcoViews.push_back( this );
|
||||
DataFile dataFile = createTCODataFiles( tcoViews );
|
||||
QPixmap thumbnail = QPixmap::grabWidget( this ).scaled(
|
||||
128, 128,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation );
|
||||
new StringPairDrag( QString( "tco_%1" ).arg(
|
||||
m_tco->getTrack()->type() ),
|
||||
dataFile.toString(), thumbnail, this );
|
||||
m_action = ToggleSelected;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if( !me->modifiers() )
|
||||
{
|
||||
if( isSelected() )
|
||||
{
|
||||
@@ -719,31 +728,22 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
|
||||
}
|
||||
else
|
||||
{
|
||||
gui->songEditor()->m_editor->selectAllTcos( false );
|
||||
m_tco->addJournalCheckPoint();
|
||||
|
||||
// move or resize
|
||||
m_tco->setJournalling( false );
|
||||
|
||||
setInitialMousePos( me->pos() );
|
||||
|
||||
if( me->x() < width() - RESIZE_GRIP_WIDTH )
|
||||
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
|
||||
if( me->x() < RESIZE_GRIP_WIDTH && sTco )
|
||||
{
|
||||
m_action = ResizeLeft;
|
||||
m_oldTime = m_tco->startPosition();
|
||||
QCursor c( Qt::SizeHorCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
s_textFloat->setTitle( tr( "Current length" ) );
|
||||
}
|
||||
else if( me->x() < width() - RESIZE_GRIP_WIDTH )
|
||||
{
|
||||
m_action = Move;
|
||||
m_oldTime = m_tco->startPosition();
|
||||
QCursor c( Qt::SizeAllCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
s_textFloat->setTitle( tr( "Current position" ) );
|
||||
delete m_hint;
|
||||
m_hint = TextFloat::displayMessage( tr( "Hint" ),
|
||||
tr( "Press <%1> and drag to make "
|
||||
"a copy." ).arg(
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
"⌘"),
|
||||
#else
|
||||
"Ctrl"),
|
||||
#endif
|
||||
embed::getIconPixmap( "hint" ), 0 );
|
||||
}
|
||||
else if( !m_tco->getAutoResize() )
|
||||
{
|
||||
@@ -752,23 +752,26 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me )
|
||||
QCursor c( Qt::SizeHorCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
s_textFloat->setTitle( tr( "Current length" ) );
|
||||
delete m_hint;
|
||||
m_hint = TextFloat::displayMessage( tr( "Hint" ),
|
||||
tr( "Press <%1> for free "
|
||||
"resizing." ).arg(
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
"⌘"),
|
||||
#else
|
||||
"Ctrl"),
|
||||
#endif
|
||||
embed::getIconPixmap( "hint" ), 0 );
|
||||
}
|
||||
// s_textFloat->reparent( this );
|
||||
// setup text-float as if TCO was already moved/resized
|
||||
mouseMoveEvent( me );
|
||||
s_textFloat->show();
|
||||
}
|
||||
}
|
||||
delete m_hint;
|
||||
QString hint = m_action == Move ? tr( "Press <%1> and drag to make "
|
||||
"a copy." )
|
||||
: tr( "Press <%1> for free "
|
||||
"resizing." );
|
||||
m_hint = TextFloat::displayMessage( tr( "Hint" ),
|
||||
hint.arg(
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
"⌘"),
|
||||
#else
|
||||
"Ctrl"),
|
||||
#endif
|
||||
embed::getIconPixmap( "hint" ), 0 );
|
||||
// s_textFloat->reparent( this );
|
||||
// setup text-float as if TCO was already moved/resized
|
||||
mouseMoveEvent( me );
|
||||
s_textFloat->show();
|
||||
}
|
||||
else if( me->button() == Qt::RightButton )
|
||||
{
|
||||
@@ -916,14 +919,43 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me )
|
||||
( *it )->movePosition( t );
|
||||
}
|
||||
}
|
||||
else if( m_action == Resize )
|
||||
else if( m_action == Resize || m_action == ResizeLeft )
|
||||
{
|
||||
MidiTime t = qMax( MidiTime::ticksPerTact() / 16, static_cast<int>( me->x() * MidiTime::ticksPerTact() / ppt ) );
|
||||
if( ! ( me->modifiers() & Qt::ControlModifier ) && me->button() == Qt::NoButton )
|
||||
if( m_action == Resize )
|
||||
{
|
||||
t = qMax<int>( MidiTime::ticksPerTact(), t.toNearestTact() );
|
||||
MidiTime t = qMax( MidiTime::ticksPerTact() / 16, static_cast<int>( me->x() * MidiTime::ticksPerTact() / ppt ) );
|
||||
if( ! ( me->modifiers() & Qt::ControlModifier ) && me->button() == Qt::NoButton )
|
||||
{
|
||||
t = qMax<int>( MidiTime::ticksPerTact(), t.toNearestTact() );
|
||||
}
|
||||
m_tco->changeLength( t );
|
||||
}
|
||||
else
|
||||
{
|
||||
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
|
||||
if( sTco )
|
||||
{
|
||||
const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x();
|
||||
|
||||
MidiTime t = qMax( 0, (int)
|
||||
m_trackView->trackContainerView()->currentPosition()+
|
||||
static_cast<int>( x * MidiTime::ticksPerTact() /
|
||||
ppt ) );
|
||||
if( ! ( me->modifiers() & Qt::ControlModifier )
|
||||
&& me->button() == Qt::NoButton )
|
||||
{
|
||||
t = t.toNearestTact();
|
||||
}
|
||||
MidiTime oldPos = m_tco->startPosition();
|
||||
if( m_tco->length() + ( oldPos - t ) >= MidiTime::ticksPerTact() )
|
||||
{
|
||||
m_tco->movePosition( t );
|
||||
m_trackView->getTrackContentWidget()->changePosition();
|
||||
m_tco->changeLength( m_tco->length() + ( oldPos - t ) );
|
||||
sTco->setStartTimeOffset( sTco->startTimeOffset() + ( oldPos - t ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
m_tco->changeLength( t );
|
||||
s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ).
|
||||
arg( m_tco->length().getTact() ).
|
||||
arg( m_tco->length().getTicks() %
|
||||
@@ -939,7 +971,9 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me )
|
||||
}
|
||||
else
|
||||
{
|
||||
if( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() )
|
||||
SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco );
|
||||
if( ( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() )
|
||||
|| ( me->x() < RESIZE_GRIP_WIDTH && !me->buttons() && sTco ) )
|
||||
{
|
||||
if( QApplication::overrideCursor() != NULL &&
|
||||
QApplication::overrideCursor()->shape() !=
|
||||
@@ -982,8 +1016,9 @@ void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * me )
|
||||
setSelected( !isSelected() );
|
||||
}
|
||||
|
||||
if( m_action == Move || m_action == Resize )
|
||||
if( m_action == Move || m_action == Resize || m_action == ResizeLeft )
|
||||
{
|
||||
// TODO: Fix m_tco->setJournalling() consistency
|
||||
m_tco->setJournalling( true );
|
||||
}
|
||||
m_action = NoAction;
|
||||
@@ -1667,12 +1702,6 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) :
|
||||
QWidget( parent ), /*!< The parent widget */
|
||||
m_trackView( parent ) /*!< The parent track view */
|
||||
{
|
||||
if( s_grip == NULL )
|
||||
{
|
||||
s_grip = new QPixmap( embed::getIconPixmap(
|
||||
"track_op_grip" ) );
|
||||
}
|
||||
|
||||
ToolTip::add( this, tr( "Press <%1> while clicking on move-grip "
|
||||
"to begin a new drag'n'drop-action." ).arg(
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
@@ -1795,14 +1824,17 @@ void TrackOperationsWidget::paintEvent( QPaintEvent * pe )
|
||||
|
||||
if( m_trackView->isMovingTrack() == false )
|
||||
{
|
||||
s_grip = new QPixmap( embed::getIconPixmap(
|
||||
"track_op_grip" ) );
|
||||
|
||||
p.drawPixmap( 2, 2, *s_grip );
|
||||
m_trackOps->show();
|
||||
m_muteBtn->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackOps->hide();
|
||||
m_muteBtn->hide();
|
||||
s_grip = new QPixmap( embed::getIconPixmap(
|
||||
"track_op_grip_c" ) );
|
||||
|
||||
p.drawPixmap( 2, 2, *s_grip );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2713,6 +2745,7 @@ void TrackView::dropEvent( QDropEvent * de )
|
||||
*/
|
||||
void TrackView::mousePressEvent( QMouseEvent * me )
|
||||
{
|
||||
|
||||
// If previously dragged too small, restore on shift-leftclick
|
||||
if( height() < DEFAULT_TRACK_HEIGHT &&
|
||||
me->modifiers() & Qt::ShiftModifier &&
|
||||
@@ -2743,9 +2776,15 @@ void TrackView::mousePressEvent( QMouseEvent * me )
|
||||
}
|
||||
else
|
||||
{
|
||||
if( me->x()>10 ) // 10 = The width of the grip + 2 pixels to the left and right.
|
||||
{
|
||||
QWidget::mousePressEvent( me );
|
||||
return;
|
||||
}
|
||||
|
||||
m_action = MoveTrack;
|
||||
|
||||
QCursor c( Qt::SizeAllCursor );
|
||||
QCursor c( Qt::SizeVerCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
// update because in move-mode, all elements in
|
||||
// track-op-widgets are hidden as a visual feedback
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "MainApplication.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "NotePlayHandle.h"
|
||||
#include "embed.h"
|
||||
@@ -242,7 +241,6 @@ int main( int argc, char * * argv )
|
||||
#endif
|
||||
|
||||
// initialize memory managers
|
||||
MemoryManager::init();
|
||||
NotePlayHandleManager::init();
|
||||
|
||||
// intialize RNG
|
||||
@@ -973,9 +971,6 @@ int main( int argc, char * * argv )
|
||||
Engine::destroy();
|
||||
}
|
||||
|
||||
// cleanup memory managers
|
||||
MemoryManager::cleanup();
|
||||
|
||||
// ProjectRenderer::updateConsoleProgress() doesn't return line after render
|
||||
if( coreOnly )
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name,
|
||||
setWindowTitle( tr( "Export project to %1" ).arg(
|
||||
QFileInfo( _file_name ).fileName() ) );
|
||||
|
||||
// get the extension of the chosen file
|
||||
// Get the extension of the chosen file.
|
||||
QStringList parts = _file_name.split( '.' );
|
||||
QString fileExt;
|
||||
if( parts.size() > 0 )
|
||||
@@ -60,16 +60,16 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name,
|
||||
{
|
||||
if( ProjectRenderer::fileEncodeDevices[i].isAvailable() )
|
||||
{
|
||||
// get the extension of this format
|
||||
// Get the extension of this format.
|
||||
QString renderExt = ProjectRenderer::fileEncodeDevices[i].m_extension;
|
||||
|
||||
// add to combo box
|
||||
// Add to combo box.
|
||||
fileFormatCB->addItem( ProjectRenderer::tr(
|
||||
ProjectRenderer::fileEncodeDevices[i].m_description ),
|
||||
QVariant(ProjectRenderer::fileEncodeDevices[i].m_fileFormat) // format tag; later used for identification
|
||||
QVariant( ProjectRenderer::fileEncodeDevices[i].m_fileFormat ) // Format tag; later used for identification.
|
||||
);
|
||||
|
||||
// if this is our extension, select it
|
||||
// If this is our extension, select it.
|
||||
if( QString::compare( renderExt, fileExt,
|
||||
Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
@@ -84,9 +84,8 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name,
|
||||
for(int i=0; i<=MAX_LEVEL; ++i)
|
||||
{
|
||||
QString info="";
|
||||
if (i==0){ info = tr("(fastest)"); }
|
||||
else if (i==4){ info = tr("(default)"); }
|
||||
else if (i==MAX_LEVEL){ info = tr("(smallest)"); }
|
||||
if ( i==0 ){ info = tr( "( Fastest - biggest )" ); }
|
||||
else if ( i==MAX_LEVEL ){ info = tr( "( Slowest - smallest )" ); }
|
||||
|
||||
compLevelCB->addItem(
|
||||
QString::number(i)+" "+info,
|
||||
@@ -95,7 +94,7 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name,
|
||||
}
|
||||
compLevelCB->setCurrentIndex(MAX_LEVEL/2);
|
||||
#ifndef LMMS_HAVE_SF_COMPLEVEL
|
||||
//Disable this widget; the setting would be ignored by the renderer.
|
||||
// Disable this widget; the setting would be ignored by the renderer.
|
||||
compressionWidget->setVisible(false);
|
||||
#endif
|
||||
|
||||
@@ -175,8 +174,8 @@ void ExportProjectDialog::startExport()
|
||||
os.setCompressionLevel(level);
|
||||
}
|
||||
|
||||
//Make sure we have the the correct file extension
|
||||
//so there's no confusion about the codec in use.
|
||||
// Make sure we have the the correct file extension
|
||||
// so there's no confusion about the codec in use.
|
||||
auto output_name = m_fileName;
|
||||
if (!(m_multiExport || output_name.endsWith(m_fileExtension,Qt::CaseInsensitive)))
|
||||
{
|
||||
@@ -190,9 +189,9 @@ void ExportProjectDialog::startExport()
|
||||
connect( m_renderManager.get(), SIGNAL( progressChanged( int ) ),
|
||||
progressBar, SLOT( setValue( int ) ) );
|
||||
connect( m_renderManager.get(), SIGNAL( progressChanged( int ) ),
|
||||
this, SLOT( updateTitleBar( int ) )) ;
|
||||
this, SLOT( updateTitleBar( int ) ));
|
||||
connect( m_renderManager.get(), SIGNAL( finished() ),
|
||||
this, SLOT( accept() ) );
|
||||
this, SLOT( accept() ) ) ;
|
||||
connect( m_renderManager.get(), SIGNAL( finished() ),
|
||||
gui->mainWindow(), SLOT( resetWindowTitle() ) );
|
||||
|
||||
@@ -250,7 +249,7 @@ void ExportProjectDialog::startBtnClicked()
|
||||
{
|
||||
m_ft = ProjectRenderer::NumFileFormats;
|
||||
|
||||
//Get file format from current menu selection.
|
||||
// Get file format from current menu selection.
|
||||
bool successful_conversion = false;
|
||||
QVariant tag = fileFormatCB->itemData(fileFormatCB->currentIndex());
|
||||
m_ft = static_cast<ProjectRenderer::ExportFileFormats>(
|
||||
|
||||
@@ -427,7 +427,7 @@ void FileBrowserTreeWidget::mousePressEvent(QMouseEvent * me )
|
||||
m_previewPlayHandle = s;
|
||||
delete tf;
|
||||
}
|
||||
else if( ( f->extension ()== "xiz" || f->extension() == "sf2" || f->extension() == "gig" ) &&
|
||||
else if( ( f->extension ()== "xiz" || f->extension() == "sf2" || f->extension() == "sf3" || f->extension() == "gig" ) &&
|
||||
! pluginFactory->pluginSupportingExtension(f->extension()).isNull() )
|
||||
{
|
||||
m_previewPlayHandle = new PresetPreviewPlayHandle( f->fullName(), f->handling() == FileItem::LoadByPlugin );
|
||||
@@ -983,7 +983,7 @@ void FileItem::determineFileType( void )
|
||||
m_type = PresetFile;
|
||||
m_handling = LoadByPlugin;
|
||||
}
|
||||
else if( ext == "sf2" )
|
||||
else if( ext == "sf2" || ext == "sf3" )
|
||||
{
|
||||
m_type = SoundFontFile;
|
||||
}
|
||||
|
||||
@@ -37,14 +37,6 @@
|
||||
#include "PluginFactory.h"
|
||||
|
||||
|
||||
static bool pluginBefore( const Plugin::Descriptor* d1, const Plugin::Descriptor* d2 )
|
||||
{
|
||||
return qstricmp( d1->displayName, d2->displayName ) < 0 ? true : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PluginBrowser::PluginBrowser( QWidget * _parent ) :
|
||||
SideBarWidget( tr( "Instrument Plugins" ),
|
||||
embed::getIconPixmap( "plugins" ).transformed( QTransform().rotate( 90 ) ), _parent )
|
||||
@@ -60,7 +52,7 @@ PluginBrowser::PluginBrowser( QWidget * _parent ) :
|
||||
view_layout->setSpacing( 5 );
|
||||
|
||||
|
||||
QLabel * hint = new QLabel( tr( "Drag an instrument "
|
||||
auto hint = new QLabel( tr( "Drag an instrument "
|
||||
"into either the Song-Editor, the "
|
||||
"Beat+Bassline Editor or into an "
|
||||
"existing instrument track." ),
|
||||
@@ -79,20 +71,20 @@ PluginBrowser::PluginBrowser( QWidget * _parent ) :
|
||||
|
||||
|
||||
|
||||
PluginBrowser::~PluginBrowser()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PluginDescList::PluginDescList(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
QList<Plugin::Descriptor*> descs = pluginFactory->descriptors(Plugin::Instrument);
|
||||
std::sort(descs.begin(), descs.end(), pluginBefore);
|
||||
std::sort(
|
||||
descs.begin(),
|
||||
descs.end(),
|
||||
[]( const Plugin::Descriptor* d1, const Plugin::Descriptor* d2 ) -> bool
|
||||
{
|
||||
return qstricmp( d1->displayName, d2->displayName ) < 0 ? true : false;
|
||||
}
|
||||
);
|
||||
for (const Plugin::Descriptor* desc : descs)
|
||||
{
|
||||
PluginDescWidget* p = new PluginDescWidget( *desc, this );
|
||||
@@ -110,23 +102,14 @@ PluginDescList::PluginDescList(QWidget *parent) :
|
||||
PluginDescWidget::PluginDescWidget( const Plugin::Descriptor & _pd,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_updateTimer( this ),
|
||||
m_pluginDescriptor( _pd ),
|
||||
m_logo( _pd.logo->pixmap() ),
|
||||
m_mouseOver( false ),
|
||||
m_targetHeight( 24 )
|
||||
m_mouseOver( false )
|
||||
{
|
||||
connect( &m_updateTimer, SIGNAL( timeout() ), SLOT( updateHeight() ) );
|
||||
setFixedHeight( m_targetHeight );
|
||||
setFixedHeight( DEFAULT_HEIGHT );
|
||||
setMouseTracking( true );
|
||||
setCursor( Qt::PointingHandCursor );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PluginDescWidget::~PluginDescWidget()
|
||||
{
|
||||
setToolTip(_pd.description);
|
||||
}
|
||||
|
||||
|
||||
@@ -159,21 +142,6 @@ void PluginDescWidget::paintEvent( QPaintEvent * e )
|
||||
p.setFont( f );
|
||||
p.drawText( 10 + logo_size.width(), 15,
|
||||
m_pluginDescriptor.displayName );
|
||||
|
||||
if( height() > 24 || m_mouseOver )
|
||||
{
|
||||
f.setBold( false );
|
||||
p.setFont( f );
|
||||
QRect br;
|
||||
p.drawText( 10 + logo_size.width(), 20, width() - 58 - 5, 999,
|
||||
Qt::TextWordWrap,
|
||||
qApp->translate( "pluginBrowser", m_pluginDescriptor.description ),
|
||||
&br );
|
||||
if( m_mouseOver )
|
||||
{
|
||||
m_targetHeight = qMax( 60, 25 + br.height() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,8 +150,7 @@ void PluginDescWidget::paintEvent( QPaintEvent * e )
|
||||
void PluginDescWidget::enterEvent( QEvent * _e )
|
||||
{
|
||||
m_mouseOver = true;
|
||||
m_targetHeight = height() + 1;
|
||||
updateHeight();
|
||||
|
||||
QWidget::enterEvent( _e );
|
||||
}
|
||||
|
||||
@@ -193,8 +160,7 @@ void PluginDescWidget::enterEvent( QEvent * _e )
|
||||
void PluginDescWidget::leaveEvent( QEvent * _e )
|
||||
{
|
||||
m_mouseOver = false;
|
||||
m_targetHeight = 24;
|
||||
updateHeight();
|
||||
|
||||
QWidget::leaveEvent( _e );
|
||||
}
|
||||
|
||||
@@ -214,30 +180,6 @@ void PluginDescWidget::mousePressEvent( QMouseEvent * _me )
|
||||
|
||||
|
||||
|
||||
void PluginDescWidget::updateHeight()
|
||||
{
|
||||
if( m_targetHeight > height() )
|
||||
{
|
||||
setFixedHeight( height() + 1 );
|
||||
}
|
||||
else if( m_targetHeight < height() )
|
||||
{
|
||||
setFixedHeight( height() - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_updateTimer.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !m_updateTimer.isActive() )
|
||||
{
|
||||
m_updateTimer.start( 10 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
* SubWindow.cpp - Implementation of QMdiSubWindow that correctly tracks
|
||||
* the geometry that windows should be restored to.
|
||||
* Workaround for https://bugreports.qt.io/browse/QTBUG-256
|
||||
* This implementation adds a custom themed title bar to
|
||||
* the subwindow.
|
||||
*
|
||||
* Copyright (c) 2015 Colin Wallace <wallace.colin.a@gmail.com>
|
||||
*
|
||||
* Copyright (c) 2016 Steffen Baranowsky <baramgb@freenet.de>
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -95,6 +97,12 @@ SubWindow::SubWindow( QWidget *parent, Qt::WindowFlags windowFlags ) :
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::paintEvent
|
||||
*
|
||||
* This draws our new title bar with custom colors
|
||||
* and draws a window icon on the left upper corner.
|
||||
*/
|
||||
void SubWindow::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QPainter p( this );
|
||||
@@ -119,6 +127,12 @@ void SubWindow::paintEvent( QPaintEvent * )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::changeEvent
|
||||
*
|
||||
* Triggers if the window title changes and calls adjustTitleBar().
|
||||
* @param event
|
||||
*/
|
||||
void SubWindow::changeEvent( QEvent *event )
|
||||
{
|
||||
QMdiSubWindow::changeEvent( event );
|
||||
@@ -133,6 +147,16 @@ void SubWindow::changeEvent( QEvent *event )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::elideText
|
||||
*
|
||||
* Stores the given text into the given label.
|
||||
* Shorts the text if it's too big for the labels width
|
||||
* ans adds three dots (...)
|
||||
*
|
||||
* @param label - holds a pointer to the QLabel
|
||||
* @param text - the text which will be stored (and if needed breaked down) into the QLabel.
|
||||
*/
|
||||
void SubWindow::elideText( QLabel *label, QString text )
|
||||
{
|
||||
QFontMetrics metrix( label->font() );
|
||||
@@ -144,6 +168,15 @@ void SubWindow::elideText( QLabel *label, QString text )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::isMaximized
|
||||
*
|
||||
* This function checks if the subwindow is maximized.
|
||||
* QMdiSubWindow::isMaximized() doesn't work on MacOS.
|
||||
* Therefore we need our own implementation for checking this
|
||||
* @return true if the subwindow is maximized at the moment.
|
||||
* false if it's not.
|
||||
*/
|
||||
bool SubWindow::isMaximized()
|
||||
{
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
@@ -161,6 +194,12 @@ bool SubWindow::isMaximized()
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::getTrueNormalGeometry
|
||||
*
|
||||
* same as QWidet::normalGeometry, but works properly under X11
|
||||
* see https://bugreports.qt.io/browse/QTBUG-256
|
||||
*/
|
||||
QRect SubWindow::getTrueNormalGeometry() const
|
||||
{
|
||||
return m_trackedNormalGeom;
|
||||
@@ -216,7 +255,15 @@ void SubWindow::setBorderColor( const QColor &c )
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::moveEvent
|
||||
*
|
||||
* overides the QMdiSubWindow::moveEvent() for saving the position
|
||||
* of the subwindow into m_trackedNormalGeom. This position
|
||||
* will be saved with the project because of an Qt bug wich doesn't
|
||||
* save the right position. look at: https://bugreports.qt.io/browse/QTBUG-256
|
||||
* @param event
|
||||
*/
|
||||
void SubWindow::moveEvent( QMoveEvent * event )
|
||||
{
|
||||
QMdiSubWindow::moveEvent( event );
|
||||
@@ -231,6 +278,14 @@ void SubWindow::moveEvent( QMoveEvent * event )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::adjustTitleBar
|
||||
*
|
||||
* Our title bar needs buttons for maximize/restore and close in the right upper corner.
|
||||
* We check if the subwindow is maximizable and put the buttons on the right positions.
|
||||
* At next we calculate the width of the title label and call elideText() for adding
|
||||
* the window title to m_windowTitle (which is a QLabel)
|
||||
*/
|
||||
void SubWindow::adjustTitleBar()
|
||||
{
|
||||
// button adjustments
|
||||
@@ -289,7 +344,6 @@ void SubWindow::adjustTitleBar()
|
||||
|
||||
|
||||
|
||||
|
||||
void SubWindow::focusChanged( QMdiSubWindow *subWindow )
|
||||
{
|
||||
if( m_hasFocus && subWindow != this )
|
||||
@@ -306,6 +360,20 @@ void SubWindow::focusChanged( QMdiSubWindow *subWindow )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief SubWindow::resizeEvent
|
||||
*
|
||||
* On every rezise event we have to adjust our title label.
|
||||
*
|
||||
* At next we give the event to QMdiSubWindow::resizeEvent() which handles
|
||||
* the event on its behavior.
|
||||
*
|
||||
* At last we store the current size into m_trackedNormalGeom. This size
|
||||
* will be saved with the project because of an Qt bug wich doesn't
|
||||
* save the right size. look at: https://bugreports.qt.io/browse/QTBUG-256
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
void SubWindow::resizeEvent( QResizeEvent * event )
|
||||
{
|
||||
adjustTitleBar();
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
QPixmap * TimeLineWidget::s_posMarkerPixmap = NULL;
|
||||
|
||||
TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt,
|
||||
Song::PlayPos & pos, const MidiTime & begin,
|
||||
Song::PlayPos & pos, const MidiTime & begin, Song::PlayModes mode,
|
||||
QWidget * parent ) :
|
||||
QWidget( parent ),
|
||||
m_inactiveLoopColor( 52, 63, 53, 64 ),
|
||||
@@ -69,6 +69,7 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt,
|
||||
m_ppt( ppt ),
|
||||
m_pos( pos ),
|
||||
m_begin( begin ),
|
||||
m_mode( mode ),
|
||||
m_savedPos( -1 ),
|
||||
m_hint( NULL ),
|
||||
m_action( NoAction ),
|
||||
@@ -370,8 +371,13 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event )
|
||||
switch( m_action )
|
||||
{
|
||||
case MovePositionMarker:
|
||||
m_pos.setTicks( t.getTicks() );
|
||||
Engine::getSong()->setToTime(t);
|
||||
m_pos.setTicks(t.getTicks());
|
||||
Engine::getSong()->setToTime(t, m_mode);
|
||||
if (!( Engine::getSong()->isPlaying()))
|
||||
{
|
||||
//Song::Mode_None is used when nothing is being played.
|
||||
Engine::getSong()->setToTime(t, Song::Mode_None);
|
||||
}
|
||||
m_pos.setCurrentFrame( 0 );
|
||||
updatePosition();
|
||||
positionMarkerMoved();
|
||||
|
||||
@@ -6,35 +6,20 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>558</width>
|
||||
<height>357</height>
|
||||
<width>504</width>
|
||||
<height>286</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>558</width>
|
||||
<height>357</height>
|
||||
<width>504</width>
|
||||
<height>286</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About LMMS</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
@@ -45,9 +30,6 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -65,7 +47,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="versionLabel">
|
||||
<property name="text">
|
||||
<string>Version %1 (%2/%3, Qt %4, %5)</string>
|
||||
<string>Version %1 (%2/%3, Qt %4, %5).</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -78,8 +60,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -106,8 +88,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -115,7 +97,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>LMMS - easy music production for everyone</string>
|
||||
<string>LMMS - easy music production for everyone.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -132,8 +114,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -141,7 +123,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="text">
|
||||
<string>Copyright © %1</string>
|
||||
<string>Copyright © %1.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -158,8 +140,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -167,7 +149,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html></string>
|
||||
<string><html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#33cc33;">https://lmms.io</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -181,8 +163,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -236,7 +218,6 @@
|
||||
</property>
|
||||
<property name="plainText">
|
||||
<string>Current language not translated (or native English).
|
||||
|
||||
If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer!</string>
|
||||
</property>
|
||||
</widget>
|
||||
@@ -278,32 +259,12 @@ If you're interested in translating LMMS in another language or want to improve
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
||||
@@ -6,34 +6,48 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>715</width>
|
||||
<height>491</height>
|
||||
<width>379</width>
|
||||
<height>374</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>519</width>
|
||||
<height>412</height>
|
||||
<width>379</width>
|
||||
<height>374</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>379</width>
|
||||
<height>374</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export project</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exportLoopCB">
|
||||
<property name="text">
|
||||
<string>Export as loop (remove extra bar)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="renderMarkersCB">
|
||||
<property name="text">
|
||||
<string>Export between loop markers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="outputGroupBox">
|
||||
<property name="title">
|
||||
<string>Output</string>
|
||||
<string>File format settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
@@ -62,7 +76,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSampleRate">
|
||||
<property name="text">
|
||||
<string>Samplerate:</string>
|
||||
<string>Sampling rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -100,12 +114,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="depthWidget" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
@@ -122,7 +130,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="labelBitDepth">
|
||||
<property name="text">
|
||||
<string>Depth:</string>
|
||||
<string>Bit depth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -133,17 +141,17 @@
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16 Bit Integer</string>
|
||||
<string>16 Bit integer</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>24 Bit Integer</string>
|
||||
<string>24 Bit integer</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>32 Bit Float</string>
|
||||
<string>32 Bit float</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -178,6 +186,11 @@
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mono</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Stereo</string>
|
||||
@@ -185,12 +198,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Joint Stereo</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mono</string>
|
||||
<string>Joint stereo</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -225,9 +233,6 @@
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maxVisibleItems">
|
||||
<number>9</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -236,9 +241,6 @@
|
||||
<item>
|
||||
<widget class="QWidget" name="bitrateWidget" native="true">
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@@ -312,8 +314,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>163</width>
|
||||
<height>20</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -341,22 +343,22 @@
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Zero Order Hold</string>
|
||||
<string>Zero order hold</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sinc Fastest</string>
|
||||
<string>Sinc worst (fastest)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sinc Medium (recommended)</string>
|
||||
<string>Sinc medium (recommended)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sinc Best (very slow!)</string>
|
||||
<string>Sinc best (slowest)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -364,7 +366,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Oversampling (use with care!):</string>
|
||||
<string>Oversampling:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -392,20 +394,6 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exportLoopCB">
|
||||
<property name="text">
|
||||
<string>Export as loop (remove end silence)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="renderMarkersCB">
|
||||
<property name="text">
|
||||
<string>Export between loop markers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
@@ -413,8 +401,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -433,8 +421,8 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
|
||||
@@ -152,7 +152,8 @@ AutomationEditor::AutomationEditor() :
|
||||
m_timeLine = new TimeLineWidget( VALUES_WIDTH, 0, m_ppt,
|
||||
Engine::getSong()->getPlayPos(
|
||||
Song::Mode_PlayAutomationPattern ),
|
||||
m_currentPosition, this );
|
||||
m_currentPosition,
|
||||
Song::Mode_PlayAutomationPattern, this );
|
||||
connect( this, SIGNAL( positionChanged( const MidiTime & ) ),
|
||||
m_timeLine, SLOT( updatePosition( const MidiTime & ) ) );
|
||||
connect( m_timeLine, SIGNAL( positionChanged( const MidiTime & ) ),
|
||||
@@ -589,6 +590,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent )
|
||||
m_editMode == DRAW ) ||
|
||||
m_editMode == ERASE )
|
||||
{
|
||||
m_drawLastTick = pos_ticks;
|
||||
m_pattern->addJournalCheckPoint();
|
||||
// erase single value
|
||||
if( it != time_map.end() )
|
||||
@@ -680,6 +682,39 @@ void AutomationEditor::mouseReleaseEvent(QMouseEvent * mouseEvent )
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomationEditor::removePoints( int x0, int x1 )
|
||||
{
|
||||
int deltax = qAbs( x1 - x0 );
|
||||
int x = x0;
|
||||
int xstep;
|
||||
|
||||
if( deltax < 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( x0 < x1 )
|
||||
{
|
||||
xstep = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xstep = -1;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while( i <= deltax )
|
||||
{
|
||||
m_pattern->removeValue( MidiTime( x ) );
|
||||
x += xstep;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent )
|
||||
{
|
||||
QMutexLocker m( &m_patternMutex );
|
||||
@@ -735,14 +770,13 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent )
|
||||
( mouseEvent->buttons() & Qt::LeftButton &&
|
||||
m_editMode == ERASE ) )
|
||||
{
|
||||
// int resolution needed to improve the sensitivity of
|
||||
// the erase manoeuvre with zoom levels < 100%
|
||||
int zoom = m_zoomingXModel.value();
|
||||
int resolution = 1 + zoom * zoom;
|
||||
for( int i = -resolution; i < resolution; ++i )
|
||||
// removing automation point
|
||||
if( pos_ticks < 0 )
|
||||
{
|
||||
m_pattern->removeValue( MidiTime( pos_ticks + i ) );
|
||||
pos_ticks = 0;
|
||||
}
|
||||
removePoints( m_drawLastTick, pos_ticks );
|
||||
Engine::getSong()->setModified();
|
||||
}
|
||||
else if( mouseEvent->buttons() & Qt::NoButton && m_editMode == DRAW )
|
||||
{
|
||||
@@ -1067,7 +1101,7 @@ inline void AutomationEditor::drawAutomationPoint( QPainter & p, timeMap::iterat
|
||||
{
|
||||
int x = xCoordOfTick( it.key() );
|
||||
int y = yCoordOfLevel( it.value() );
|
||||
const int outerRadius = qBound( 2, ( m_ppt * AutomationPattern::quantization() ) / 576, 5 ); // man, getting this calculation right took forever
|
||||
const int outerRadius = qBound( 3, ( m_ppt * AutomationPattern::quantization() ) / 576, 5 ); // man, getting this calculation right took forever
|
||||
p.setPen( QPen( vertexColor().lighter( 200 ) ) );
|
||||
p.setBrush( QBrush( vertexColor() ) );
|
||||
p.drawEllipse( x - outerRadius, y - outerRadius, outerRadius * 2, outerRadius * 2 );
|
||||
|
||||
@@ -311,7 +311,8 @@ PianoRoll::PianoRoll() :
|
||||
m_timeLine = new TimeLineWidget( WHITE_KEY_WIDTH, 0, m_ppt,
|
||||
Engine::getSong()->getPlayPos(
|
||||
Song::Mode_PlayPattern ),
|
||||
m_currentPosition, this );
|
||||
m_currentPosition,
|
||||
Song::Mode_PlayPattern, this );
|
||||
connect( this, SIGNAL( positionChanged( const MidiTime & ) ),
|
||||
m_timeLine, SLOT( updatePosition( const MidiTime & ) ) );
|
||||
connect( m_timeLine, SIGNAL( positionChanged( const MidiTime & ) ),
|
||||
@@ -961,6 +962,9 @@ void PianoRoll::shiftSemiTone( int amount ) // shift notes by amount semitones
|
||||
}
|
||||
}
|
||||
|
||||
m_pattern->rearrangeAllNotes();
|
||||
m_pattern->dataChanged();
|
||||
|
||||
// we modified the song
|
||||
update();
|
||||
gui->songEditor()->update();
|
||||
@@ -1668,10 +1672,10 @@ void PianoRoll::mousePressEvent(QMouseEvent * me )
|
||||
// clicked on keyboard on the left
|
||||
if( me->buttons() == Qt::RightButton )
|
||||
{
|
||||
// right click, tone marker contextual menu
|
||||
// right click - tone marker contextual menu
|
||||
m_semiToneMarkerMenu->popup( mapToGlobal( QPoint( me->x(), me->y() ) ) );
|
||||
}
|
||||
else
|
||||
else if( me->buttons() == Qt::LeftButton )
|
||||
{
|
||||
// left click - play the note
|
||||
int v = ( (float) x ) / ( (float) WHITE_KEY_WIDTH ) * MidiDefaultVelocity;
|
||||
|
||||
@@ -89,7 +89,8 @@ SongEditor::SongEditor( Song * song ) :
|
||||
m_timeLine = new TimeLineWidget( widgetTotal, 32,
|
||||
pixelsPerTact(),
|
||||
m_song->m_playPos[Song::Mode_PlaySong],
|
||||
m_currentPosition, this );
|
||||
m_currentPosition,
|
||||
Song::Mode_PlaySong, this );
|
||||
connect( this, SIGNAL( positionChanged( const MidiTime & ) ),
|
||||
m_song->m_playPos[Song::Mode_PlaySong].m_timeLine,
|
||||
SLOT( updatePosition( const MidiTime & ) ) );
|
||||
|
||||
@@ -101,19 +101,21 @@ void TimeDisplayWidget::updateTime()
|
||||
switch( m_displayMode )
|
||||
{
|
||||
case MinutesSeconds:
|
||||
m_majorLCD.setValue( s->getMilliseconds() / 60000 );
|
||||
m_minorLCD.setValue( ( s->getMilliseconds() / 1000 ) % 60 );
|
||||
m_milliSecondsLCD.setValue( s->getMilliseconds() % 1000 );
|
||||
int msec;
|
||||
msec = s->getMilliseconds();
|
||||
m_majorLCD.setValue(msec / 60000);
|
||||
m_minorLCD.setValue((msec / 1000) % 60);
|
||||
m_milliSecondsLCD.setValue(msec % 1000);
|
||||
break;
|
||||
|
||||
case BarsTicks:
|
||||
int tick;
|
||||
tick = ( s->getMilliseconds() * s->getTempo() * (DefaultTicksPerTact / 4 ) ) / 60000 ;
|
||||
m_majorLCD.setValue( (int)(tick / s->ticksPerTact() ) + 1);
|
||||
m_minorLCD.setValue( ( tick % s->ticksPerTact() ) /
|
||||
( s->ticksPerTact() / s->getTimeSigModel().getNumerator() ) +1 );
|
||||
m_milliSecondsLCD.setValue( ( tick % s->ticksPerTact() ) %
|
||||
( s->ticksPerTact() / s->getTimeSigModel().getNumerator() ) );
|
||||
tick = s->getPlayPos().getTicks();
|
||||
m_majorLCD.setValue((int)(tick / s->ticksPerTact()) + 1);
|
||||
m_minorLCD.setValue((tick % s->ticksPerTact()) /
|
||||
(s->ticksPerTact() / s->getTimeSigModel().getNumerator() ) +1);
|
||||
m_milliSecondsLCD.setValue((tick % s->ticksPerTact()) %
|
||||
(s->ticksPerTact() / s->getTimeSigModel().getNumerator()));
|
||||
break;
|
||||
|
||||
default: break;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#cmakedefine LMMS_HAVE_ALSA
|
||||
#cmakedefine LMMS_HAVE_FLUIDSYNTH
|
||||
#cmakedefine LMMS_HAVE_JACK
|
||||
#cmakedefine LMMS_HAVE_WEAKJACK
|
||||
#cmakedefine LMMS_HAVE_MP3LAME
|
||||
#cmakedefine LMMS_HAVE_OGGVORBIS
|
||||
#cmakedefine LMMS_HAVE_OSS
|
||||
|
||||
@@ -442,12 +442,15 @@ void InstrumentTrack::silenceAllNotes( bool removeIPH )
|
||||
m_midiNotesMutex.unlock();
|
||||
|
||||
lock();
|
||||
// invalidate all NotePlayHandles linked to this track
|
||||
// invalidate all NotePlayHandles and PresetPreviewHandles linked to this track
|
||||
m_processHandles.clear();
|
||||
Engine::mixer()->removePlayHandlesOfTypes( this, removeIPH
|
||||
? PlayHandle::TypeNotePlayHandle
|
||||
| PlayHandle::TypeInstrumentPlayHandle
|
||||
: PlayHandle::TypeNotePlayHandle );
|
||||
|
||||
quint8 flags = PlayHandle::TypeNotePlayHandle | PlayHandle::TypePresetPreviewHandle;
|
||||
if( removeIPH )
|
||||
{
|
||||
flags |= PlayHandle::TypeInstrumentPlayHandle;
|
||||
}
|
||||
Engine::mixer()->removePlayHandlesOfTypes( this, flags );
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -215,28 +215,7 @@ Note * Pattern::addNote( const Note & _new_note, const bool _quant_pos )
|
||||
}
|
||||
|
||||
instrumentTrack()->lock();
|
||||
if( m_notes.size() == 0 || m_notes.back()->pos() <= new_note->pos() )
|
||||
{
|
||||
m_notes.push_back( new_note );
|
||||
}
|
||||
else
|
||||
{
|
||||
// simple algorithm for inserting the note between two
|
||||
// notes with smaller and greater position
|
||||
// maybe it could be optimized by starting in the middle and
|
||||
// going forward or backward but note-inserting isn't that
|
||||
// time-critical since it is usually not done while playing...
|
||||
long new_note_abs_time = new_note->pos();
|
||||
NoteVector::Iterator it = m_notes.begin();
|
||||
|
||||
while( it != m_notes.end() &&
|
||||
( *it )->pos() < new_note_abs_time )
|
||||
{
|
||||
++it;
|
||||
}
|
||||
|
||||
m_notes.insert( it, new_note );
|
||||
}
|
||||
m_notes.insert(std::upper_bound(m_notes.begin(), m_notes.end(), new_note, Note::lessThan), new_note);
|
||||
instrumentTrack()->unlock();
|
||||
|
||||
checkType();
|
||||
@@ -294,7 +273,7 @@ Note * Pattern::noteAtStep( int _step )
|
||||
void Pattern::rearrangeAllNotes()
|
||||
{
|
||||
// sort notes by start time
|
||||
qSort(m_notes.begin(), m_notes.end(), Note::lessThan );
|
||||
std::sort(m_notes.begin(), m_notes.end(), Note::lessThan);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ void SampleTCO::setSampleBuffer( SampleBuffer* sb )
|
||||
void SampleTCO::setSampleFile( const QString & _sf )
|
||||
{
|
||||
m_sampleBuffer->setAudioFile( _sf );
|
||||
setStartTimeOffset( 0 );
|
||||
changeLength( (int) ( m_sampleBuffer->frames() / Engine::framesPerTick() ) );
|
||||
|
||||
emit sampleChanged();
|
||||
@@ -183,11 +184,17 @@ void SampleTCO::updateTrackTcos()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool SampleTCO::isPlaying() const
|
||||
{
|
||||
return m_isPlaying;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::setIsPlaying(bool isPlaying)
|
||||
{
|
||||
m_isPlaying = isPlaying;
|
||||
@@ -241,6 +248,7 @@ void SampleTCO::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
_this.setAttribute( "len", length() );
|
||||
_this.setAttribute( "muted", isMuted() );
|
||||
_this.setAttribute( "src", sampleFile() );
|
||||
_this.setAttribute( "off", startTimeOffset() );
|
||||
if( sampleFile() == "" )
|
||||
{
|
||||
QString s;
|
||||
@@ -265,6 +273,7 @@ void SampleTCO::loadSettings( const QDomElement & _this )
|
||||
}
|
||||
changeLength( _this.attribute( "len" ).toInt() );
|
||||
setMuted( _this.attribute( "muted" ).toInt() );
|
||||
setStartTimeOffset( _this.attribute( "off" ).toInt() );
|
||||
}
|
||||
|
||||
|
||||
@@ -369,6 +378,8 @@ void SampleTCOView::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
if( StringPairDrag::decodeKey( _de ) == "samplefile" )
|
||||
@@ -501,8 +512,9 @@ void SampleTCOView::paintEvent( QPaintEvent * pe )
|
||||
float nom = Engine::getSong()->getTimeSigModel().getNumerator();
|
||||
float den = Engine::getSong()->getTimeSigModel().getDenominator();
|
||||
float ticksPerTact = DefaultTicksPerTact * nom / den;
|
||||
|
||||
QRect r = QRect( TCO_BORDER_WIDTH, spacing,
|
||||
|
||||
float offset = m_tco->startTimeOffset() / ticksPerTact * pixelsPerTact();
|
||||
QRect r = QRect( TCO_BORDER_WIDTH + offset, spacing,
|
||||
qMax( static_cast<int>( m_tco->sampleLength() * ppt / ticksPerTact ), 1 ), rect().bottom() - 2 * spacing );
|
||||
m_tco->m_sampleBuffer->visualize( p, r, pe->rect() );
|
||||
|
||||
@@ -608,10 +620,10 @@ bool SampleTrack::play( const MidiTime & _start, const fpp_t _frames,
|
||||
float framesPerTick = Engine::framesPerTick();
|
||||
if( _start >= sTco->startPosition() && _start < sTco->endPosition() )
|
||||
{
|
||||
if( sTco->isPlaying() == false )
|
||||
if( sTco->isPlaying() == false && _start > sTco->startPosition() + sTco->startTimeOffset() )
|
||||
{
|
||||
f_cnt_t sampleStart = framesPerTick * ( _start - sTco->startPosition() );
|
||||
f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() );
|
||||
f_cnt_t sampleStart = framesPerTick * ( _start - sTco->startPosition() - sTco->startTimeOffset() );
|
||||
f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() - sTco->startTimeOffset() );
|
||||
f_cnt_t sampleBufferLength = sTco->sampleBuffer()->frames();
|
||||
//if the Tco smaller than the sample length we play only until Tco end
|
||||
//else we play the sample to the end but nothing more
|
||||
|
||||
Reference in New Issue
Block a user