Merge branch 'stable-1.1'

Conflicts:
	include/Plugin.h
	src/core/Plugin.cpp
This commit is contained in:
Vesa
2014-09-02 16:59:04 +03:00
126 changed files with 2422 additions and 1061 deletions

View File

@@ -40,6 +40,7 @@
#include "SongEditor.h"
#include "Effect.h"
#include "lmmsversion.h"
#include "base64.h"
// bbTCO::defaultColor()
#include "bb_track.h"

View File

@@ -38,7 +38,6 @@
#include "config_mgr.h"
#include "SamplePlayHandle.h"
#include "PianoRoll.h"
#include "MicroTimer.h"
#include "atomic_int.h"
// platform-specific audio-interface-classes
@@ -69,7 +68,6 @@ Mixer::Mixer() :
m_inputBufferWrite( 1 ),
m_readBuf( NULL ),
m_writeBuf( NULL ),
m_cpuLoad( 0 ),
m_workers(),
m_numWorkers( QThread::idealThreadCount()-1 ),
m_queueReadyWaitCond(),
@@ -77,7 +75,8 @@ Mixer::Mixer() :
m_masterGain( 1.0f ),
m_audioDev( NULL ),
m_oldAudioDev( NULL ),
m_globalMutex( QMutex::Recursive )
m_globalMutex( QMutex::Recursive ),
m_profiler()
{
for( int i = 0; i < 2; ++i )
{
@@ -277,7 +276,7 @@ sample_rate_t Mixer::processingSampleRate() const
bool Mixer::criticalXRuns() const
{
return m_cpuLoad >= 99 && engine::getSong()->isExporting() == false;
return cpuLoad() >= 99 && engine::getSong()->isExporting() == false;
}
@@ -315,7 +314,8 @@ void Mixer::pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames )
const surroundSampleFrame * Mixer::renderNextBuffer()
{
MicroTimer timer;
m_profiler.startPeriod();
static song::playPos last_metro_pos = -1;
song::playPos p = engine::getSong()->getPlayPos(
@@ -428,10 +428,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
Controller::triggerFrameCounter();
AutomatableModel::incrementPeriodCounter();
const float new_cpu_load = timer.elapsed() / 10000.0f *
processingSampleRate() / m_framesPerPeriod;
m_cpuLoad = tLimit( (int) ( new_cpu_load * 0.1f + m_cpuLoad * 0.9f ), 0,
100 );
m_profiler.finishPeriod( processingSampleRate(), m_framesPerPeriod );
return m_readBuf;
}

View File

@@ -0,0 +1,63 @@
/*
* MixerProfiler.cpp - class for profiling performance of Mixer
*
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* 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 "MixerProfiler.h"
MixerProfiler::MixerProfiler() :
m_periodTimer(),
m_cpuLoad( 0 ),
m_outputFile()
{
}
MixerProfiler::~MixerProfiler()
{
}
void MixerProfiler::finishPeriod( sample_rate_t sampleRate, fpp_t framesPerPeriod )
{
int periodElapsed = m_periodTimer.elapsed();
const float newCpuLoad = periodElapsed / 10000.0f * sampleRate / framesPerPeriod;
m_cpuLoad = qBound<int>( 0, ( newCpuLoad * 0.1f + m_cpuLoad * 0.9f ), 100 );
if( m_outputFile.isOpen() )
{
m_outputFile.write( QString( "%1\n" ).arg( periodElapsed ).toLatin1() );
}
}
void MixerProfiler::setOutputFile( const QString& outputFile )
{
m_outputFile.close();
m_outputFile.setFileName( outputFile );
m_outputFile.open( QFile::WriteOnly | QFile::Truncate );
}

View File

@@ -1,9 +1,7 @@
#ifndef SINGLE_SOURCE_COMPILE
/*
* Plugin.cpp - implementation of plugin-class including plugin-loader
*
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -24,9 +22,10 @@
*
*/
#include <QDir>
#include <QLibrary>
#include <QMessageBox>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QtGui/QMessageBox>
#include "Plugin.h"
#include "embed.h"
@@ -54,9 +53,9 @@ static Plugin::Descriptor dummy_plugin_descriptor =
Plugin::Plugin( const Descriptor * _descriptor, Model * _parent ) :
Plugin::Plugin( const Descriptor * _descriptor, Model * parent ) :
JournallingObject(),
Model( _parent ),
Model( parent ),
m_descriptor( _descriptor )
{
if( m_descriptor == NULL )
@@ -91,89 +90,80 @@ AutomatableModel * Plugin::childModel( const QString & )
Plugin * Plugin::instantiate( const QString & _plugin_name, Model * _parent,
void * _data )
Plugin * Plugin::instantiate( const QString & pluginName, Model * parent,
void * data )
{
QLibrary plugin_lib( configManager::inst()->pluginDir() +
_plugin_name );
if( plugin_lib.load() == false )
QLibrary pluginLibrary( configManager::inst()->pluginDir() + pluginName );
if( pluginLibrary.load() == false )
{
if( engine::hasGUI() )
{
QMessageBox::information( NULL,
tr( "Plugin not found" ),
tr( "The plugin \"%1\" wasn't found "
"or could not be loaded!\n"
"Reason: \"%2\"" ).arg( _plugin_name ).
arg( plugin_lib.errorString() ),
QMessageBox::Ok |
QMessageBox::Default );
tr( "The plugin \"%1\" wasn't found or could not be loaded!\nReason: \"%2\"" ).
arg( pluginName ).arg( pluginLibrary.errorString() ),
QMessageBox::Ok | QMessageBox::Default );
}
return new DummyPlugin();
}
instantiationHook inst_hook = ( instantiationHook ) plugin_lib.resolve(
"lmms_plugin_main" );
if( inst_hook == NULL )
InstantiationHook instantiationHook = ( InstantiationHook ) pluginLibrary.resolve( "lmms_plugin_main" );
if( instantiationHook == NULL )
{
if( engine::hasGUI() )
{
QMessageBox::information( NULL,
tr( "Error while loading plugin" ),
tr( "Failed to load plugin \"%1\"!"
).arg( _plugin_name ),
QMessageBox::Ok |
QMessageBox::Default );
tr( "Failed to load plugin \"%1\"!").arg( pluginName ),
QMessageBox::Ok | QMessageBox::Default );
}
return new DummyPlugin();
}
Plugin * inst = inst_hook( _parent, _data );
Plugin * inst = instantiationHook( parent, data );
return inst;
}
void Plugin::getDescriptorsOfAvailPlugins( DescriptorList & _plugin_descs )
void Plugin::getDescriptorsOfAvailPlugins( DescriptorList& pluginDescriptors )
{
QDir directory( configManager::inst()->pluginDir() );
#ifdef LMMS_BUILD_WIN32
QFileInfoList list = directory.entryInfoList(
QStringList( "*.dll" ) );
QFileInfoList list = directory.entryInfoList( QStringList( "*.dll" ) );
#else
QFileInfoList list = directory.entryInfoList(
QStringList( "lib*.so" ) );
QFileInfoList list = directory.entryInfoList( QStringList( "lib*.so" ) );
#endif
foreach( const QFileInfo & f, list )
foreach( const QFileInfo& f, list )
{
QLibrary( f.absoluteFilePath() ).load();
}
foreach( const QFileInfo & f, list )
foreach( const QFileInfo& f, list )
{
QLibrary plugin_lib( f.absoluteFilePath() );
if( plugin_lib.load() == false ||
plugin_lib.resolve( "lmms_plugin_main" ) == NULL )
QLibrary pluginLibrary( f.absoluteFilePath() );
if( pluginLibrary.load() == false ||
pluginLibrary.resolve( "lmms_plugin_main" ) == NULL )
{
continue;
}
QString desc_name = f.fileName().section( '.', 0, 0 ) +
"_plugin_descriptor";
if( desc_name.left( 3 ) == "lib" )
QString descriptorName = f.baseName() + "_plugin_descriptor";
if( descriptorName.left( 3 ) == "lib" )
{
desc_name = desc_name.mid( 3 );
descriptorName = descriptorName.mid( 3 );
}
Descriptor * plugin_desc =
(Descriptor *) plugin_lib.resolve(
desc_name.toUtf8().constData() );
if( plugin_desc == NULL )
Descriptor* pluginDescriptor = (Descriptor *) pluginLibrary.resolve( descriptorName.toUtf8().constData() );
if( pluginDescriptor == NULL )
{
printf( "LMMS plugin %s does not have a "
"plugin descriptor named %s!\n",
f.absoluteFilePath().toUtf8().constData(),
desc_name.toUtf8().constData() );
qWarning() << tr( "LMMS plugin %1 does not have a plugin descriptor named %2!" ).
arg( f.absoluteFilePath() ).arg( descriptorName );
continue;
}
_plugin_descs.push_back( *plugin_desc );
pluginDescriptors += *pluginDescriptor;
}
}
@@ -181,9 +171,9 @@ void Plugin::getDescriptorsOfAvailPlugins( DescriptorList & _plugin_descs )
PluginView * Plugin::createView( QWidget * _parent )
PluginView * Plugin::createView( QWidget * parent )
{
PluginView * pv = instantiateView( _parent );
PluginView * pv = instantiateView( parent );
if( pv != NULL )
{
pv->setModel( this );
@@ -227,4 +217,3 @@ QDomElement Plugin::Descriptor::SubPluginFeatures::Key::saveXML(
}
#endif

View File

@@ -95,7 +95,7 @@ int main( int argc, char * * argv )
bool core_only = false;
bool fullscreen = true;
bool exit_after_import = false;
QString file_to_load, file_to_save, file_to_import, render_out;
QString file_to_load, file_to_save, file_to_import, render_out, profilerOutputFile;
for( int i = 1; i < argc; ++i )
{
@@ -341,6 +341,11 @@ int main( int argc, char * * argv )
exit_after_import = true;
}
}
else if( argc > i && ( QString( argv[i] ) == "--profile" || QString( argv[i] ) == "-p" ) )
{
profilerOutputFile = argv[i+1];
++i;
}
else
{
if( argv[i][0] == '-' )
@@ -496,6 +501,11 @@ int main( int argc, char * * argv )
SLOT( updateConsoleProgress() ) );
t->start( 200 );
if( profilerOutputFile.isEmpty() == false )
{
engine::mixer()->profiler().setOutputFile( profilerOutputFile );
}
// start now!
r->startProcessing();
}

View File

@@ -619,70 +619,53 @@ PianoRoll::PianoRoll() :
tb_layout->addWidget( m_chordComboBox );
tb_layout->addStretch();
m_zoomingComboBox->setWhatsThis( tr(
"This controls the magnification over time. "
"It can be useful choose a magnification for a specific task. "
"For ordinary editing, the magnification should be fitted to your "
"smallest used notes. "
"Most will use the default magnification of 100%, "
"when the shortest notes are 1/16. "
"If you have used shorter notes, your editing will be easier, "
"with a magnification of 200%, or more. "
"You should use low magnification, if you need to move a block "
"of notes many bars, or just to get an overview of the score."
) );
m_quantizeComboBox->setWhatsThis( tr(
"This 'Q' stands for quantification, and controls the minimum spacing "
"between notes. "
"In piano-roll this is very important, when you make syncopated patterns, "
"and an absolute must, for swing-notes! "
"Observe that the score segmentation also changes, depending on the selected Q. "
"You should not use a Q-value that does not fit your chosen time-signature! "
"The default value is 1/16, and that fits the default 4/4 timing. "
"A Q of 1/16 will also work well in most editing."
) );
m_noteLenComboBox->setWhatsThis( tr(
"This lets you select the note you place in the score. "
"In most circumstances the best choice is 'Last Note'."
"The choice 'Last Note' means that LMMS will use the note you last clicked, "
"when you place the next note. "
"But you can choose any note-length from this drop-down, "
"and your choice will be the note, that you can draw in the score."
) );
m_scaleComboBox->setWhatsThis( tr(
"This lets you select a music scale that LMMS then will annotate. "
"The feature is directly connected to the context-menu "
"on the virtual keyboard, to the left. "
"First you chose which scale you will use. "
"You do that in this very dropdown! "
"Then you choose the key of your composition. "
"Right mouse click on the selected key in the virtual keyboard, "
"and then choose 'Mark current Scale' "
"LMMS will annotate all notes that belongs to the chosen scale, "
"and in the key you have selected! "
"LMMS will not only annotate in the score you have open, "
"but all scores in your project, will be correctly annotated. "
"This will help you avoid using bum-notes, as you compose. "
"You should know about principle scales in music. "
"Search the net, if you do not! "
) );
m_chordComboBox->setWhatsThis( tr(
"This lets you select a standard music chord. "
"All notes that are played simultaneous, are 'chords',"
"but a large number of simultaneous key combinations, has own names, "
"and its own place in music. "
"They are standard chords, and it is these chords, "
"you can find in this drop-down. "
"After you have selected a chord, any click in the score, "
"will place that chord, musically correctly, "
"and with the Left mouse clicked note, as the root-note in the chord! "
"To return to single note placement, you need to choose 'No chord' "
"in this drop-down!"
) );
m_zoomingComboBox->setWhatsThis(
tr(
"This controls the magnification of an axis. "
"It can be helpful to choose magnification for a specific "
"task. For ordinary editing, the magnification should be "
"fitted to your smallest notes. "
) );
m_quantizeComboBox->setWhatsThis(
tr(
"The 'Q' stands for quantization, and controls the grid size "
"notes and control points snap to. "
"With smaller quantization values, you can draw shorter notes "
"in Piano Roll, and more exact control points in the "
"Automation Editor."
) );
m_noteLenComboBox->setWhatsThis(
tr(
"This lets you select the length of new notes. "
"'Last Note' means that LMMS will use the note length of "
"the note you last edited"
) );
m_scaleComboBox->setWhatsThis(
tr(
"The feature is directly connected to the context-menu "
"on the virtual keyboard, to the left in Piano Roll. "
"After you have chosen the scale you want "
"in this drop-down menu, "
"you can right click on a desired key in the virtual keyboard, "
"and then choose 'Mark current Scale'. "
"LMMS will highlight all notes that belongs to the chosen scale, "
"and in the key you have selected!"
) );
m_chordComboBox->setWhatsThis(
tr(
"Let you select a chord which LMMS then can draw or highlight."
"You can find the most common chords in this drop-down menu. "
"After you have selected a chord, click anywhere to place the chord, and right "
"click on the virtual keyboard to open context menu and highlight the chord. "
"To return to single note placement, you need to choose 'No chord' "
"in this drop-down menu."
) );
// setup our actual window
setFocusPolicy( Qt::StrongFocus );