Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions include/DataFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,6 @@ class EXPORT DataFile : public QDomDocument
return m_type;
}

// small helper class for adjusting application's locale settings
// when loading or saving floating point values rendered to strings
class LocaleHelper
{
public:
enum Modes
{
ModeLoad,
ModeSave,
ModeCount
};
typedef Modes Mode;

LocaleHelper( Mode mode );
~LocaleHelper();

};


private:
static Type type( const QString& typeName );
static QString typeName( Type type );
Expand Down
67 changes: 67 additions & 0 deletions include/LocaleHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* LocaleHelper.h - compatibility functions for handling decimal separators
* Providing helper functions which handle both periods and commas
* for decimal separators to load old projects correctly
*
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2018 Hyunjin Song <tteu.ingog/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#ifndef LOCALEHELPER_H
#define LOCALEHELPER_H

#include <QLocale>

#include <limits>
#include <cmath>

namespace LocaleHelper
{
inline double toDouble(QString str, bool* ok = nullptr)
{
bool isOkay;
double value;
QLocale c(QLocale::C);
c.setNumberOptions(QLocale::RejectGroupSeparator);
value = c.toDouble(str, &isOkay);
if (!isOkay)
{
QLocale german(QLocale::German);
german.setNumberOptions(QLocale::RejectGroupSeparator);
value = german.toDouble(str, &isOkay);
}
if (ok != nullptr) {*ok = isOkay;}
return value;
}

inline float toFloat(QString str, bool* ok = nullptr)
{
double d = toDouble(str, ok);
if (!std::isinf(d) && std::fabs(d) > std::numeric_limits<float>::max())
{
if (ok != nullptr) {*ok = false;}
return 0.0f;
}
return static_cast<float>(d);
}
}

#endif // LOCALEHELPER_H
7 changes: 4 additions & 3 deletions plugins/MidiExport/MidiExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "TrackContainer.h"
#include "BBTrack.h"
#include "InstrumentTrack.h"
#include "LocaleHelper.h"


extern "C"
Expand Down Expand Up @@ -133,7 +134,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks,
{
base_pitch += masterPitch;
}
base_volume = it.attribute("volume", "100").toDouble()/100.0;
base_volume = LocaleHelper::toDouble(it.attribute("volume", "100"))/100.0;
}

if (n.nodeName() == "pattern")
Expand Down Expand Up @@ -204,7 +205,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks,
{
base_pitch += masterPitch;
}
base_volume = it.attribute("volume", "100").toDouble() / 100.0;
base_volume = LocaleHelper::toDouble(it.attribute("volume", "100")) / 100.0;
}

if (n.nodeName() == "pattern")
Expand Down Expand Up @@ -273,7 +274,7 @@ void MidiExport::writePattern(MidiNoteVector &pat, QDomNode n,
// TODO interpret pan="0" fxch="0" pitchrange="1"
MidiNote mnote;
mnote.pitch = qMax(0, qMin(127, note.attribute("key", "0").toInt() + base_pitch));
mnote.volume = qMin(qRound(base_volume * note.attribute("vol", "100").toDouble()), 127);
mnote.volume = qMin(qRound(base_volume * LocaleHelper::toDouble(note.attribute("vol", "100"))), 127);
mnote.time = base_time + note.attribute("pos", "0").toInt();
mnote.duration = note.attribute("len", "0").toInt();
pat.push_back(mnote);
Expand Down
9 changes: 5 additions & 4 deletions plugins/VstEffect/VstEffectControls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "VstEffectControls.h"
#include "VstEffect.h"

#include "LocaleHelper.h"
#include "MainWindow.h"
#include "GuiApplication.h"
#include <QMdiArea>
Expand Down Expand Up @@ -85,8 +86,8 @@ void VstEffectControls::loadSettings( const QDomElement & _this )
if( !( knobFModel[ i ]->isAutomated() ||
knobFModel[ i ]->controllerConnection() ) )
{
knobFModel[ i ]->setValue( (s_dumpValues.at( 2 ) ).toFloat() );
knobFModel[ i ]->setInitValue( (s_dumpValues.at( 2 ) ).toFloat() );
knobFModel[ i ]->setValue(LocaleHelper::toFloat(s_dumpValues.at(2)));
knobFModel[ i ]->setInitValue(LocaleHelper::toFloat(s_dumpValues.at(2)));
}

connect( knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
Expand Down Expand Up @@ -381,7 +382,7 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls *
if( !hasKnobModel )
{
sprintf( paramStr, "%d", i);
m_vi->knobFModel[ i ] = new FloatModel( ( s_dumpValues.at( 2 ) ).toFloat(),
m_vi->knobFModel[ i ] = new FloatModel( LocaleHelper::toFloat(s_dumpValues.at(2)),
0.0f, 1.0f, 0.01f, _eff, tr( paramStr ) );
}
connect( m_vi->knobFModel[ i ], SIGNAL( dataChanged() ), this,
Expand Down Expand Up @@ -445,7 +446,7 @@ void manageVSTEffectView::syncPlugin( void )
{
sprintf( paramStr, "param%d", i );
s_dumpValues = dump[ paramStr ].split( ":" );
f_value = ( s_dumpValues.at( 2 ) ).toFloat();
f_value = LocaleHelper::toFloat(s_dumpValues.at(2));
m_vi2->knobFModel[ i ]->setAutomatedValue( f_value );
m_vi2->knobFModel[ i ]->setInitValue( f_value );
}
Expand Down
9 changes: 5 additions & 4 deletions plugins/vestige/vestige.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "InstrumentPlayHandle.h"
#include "InstrumentTrack.h"
#include "VstPlugin.h"
#include "LocaleHelper.h"
#include "MainWindow.h"
#include "Mixer.h"
#include "GuiApplication.h"
Expand Down Expand Up @@ -203,8 +204,8 @@ void vestigeInstrument::loadSettings( const QDomElement & _this )

if( !( knobFModel[ i ]->isAutomated() || knobFModel[ i ]->controllerConnection() ) )
{
knobFModel[ i ]->setValue( ( s_dumpValues.at( 2 )).toFloat() );
knobFModel[ i ]->setInitValue( ( s_dumpValues.at( 2 )).toFloat() );
knobFModel[ i ]->setValue(LocaleHelper::toFloat(s_dumpValues.at(2)));
knobFModel[ i ]->setInitValue(LocaleHelper::toFloat(s_dumpValues.at(2)));
}

connect( knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
Expand Down Expand Up @@ -991,7 +992,7 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume
if( !hasKnobModel )
{
sprintf( paramStr, "%d", i);
m_vi->knobFModel[ i ] = new FloatModel( (s_dumpValues.at( 2 )).toFloat(),
m_vi->knobFModel[ i ] = new FloatModel( LocaleHelper::toFloat(s_dumpValues.at(2)),
0.0f, 1.0f, 0.01f, castModel<vestigeInstrument>(), tr( paramStr ) );
}
connect( m_vi->knobFModel[i], SIGNAL( dataChanged() ), this, SLOT( setParameter() ) );
Expand Down Expand Up @@ -1052,7 +1053,7 @@ void manageVestigeInstrumentView::syncPlugin( void )
{
sprintf( paramStr, "param%d", i );
s_dumpValues = dump[ paramStr ].split( ":" );
f_value = ( s_dumpValues.at( 2 ) ).toFloat();
f_value = LocaleHelper::toFloat(s_dumpValues.at(2));
m_vi->knobFModel[ i ]->setAutomatedValue( f_value );
m_vi->knobFModel[ i ]->setInitValue( f_value );
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/vst_base/VstPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

#include "ConfigManager.h"
#include "GuiApplication.h"
#include "LocaleHelper.h"
#include "MainWindow.h"
#include "Mixer.h"
#include "Song.h"
Expand Down Expand Up @@ -299,7 +300,7 @@ void VstPlugin::setParameterDump( const QMap<QString, QString> & _pdump )
{
( *it ).section( ':', 0, 0 ).toInt(),
"",
( *it ).section( ':', 2, -1 ).toFloat()
LocaleHelper::toFloat((*it).section(':', 2, -1))
} ;
m.addInt( item.index );
m.addString( item.shortLabel );
Expand Down
9 changes: 5 additions & 4 deletions plugins/zynaddsubfx/zynaddsubfx/src/Misc/QtXmlWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
// Include LMMS headers
#include "lmmsconfig.h"
#include "IoHelper.h"
#include "LocaleHelper.h"


struct XmlData
Expand Down Expand Up @@ -228,14 +229,14 @@ int QtXmlWrapper::dosavefile(const char *filename,

void QtXmlWrapper::addpar(const std::string &name, int val)
{
d->addparams("par", 2, "name", name.c_str(), "value", stringFrom<int>(
val).c_str());
d->addparams("par", 2, "name", name.c_str(), "value",
QString::number(val).toLocal8Bit().constData());
}

void QtXmlWrapper::addparreal(const std::string &name, float val)
{
d->addparams("par_real", 2, "name", name.c_str(), "value",
stringFrom<float>(val).c_str());
QString::number(val, 'f').toLocal8Bit().constData());
}

void QtXmlWrapper::addparbool(const std::string &name, int val)
Expand Down Expand Up @@ -510,7 +511,7 @@ float QtXmlWrapper::getparreal(const char *name, float defaultpar) const
return defaultpar;
}

return QLocale().toFloat( tmp.attribute( "value" ) );
return LocaleHelper::toFloat( tmp.attribute( "value" ) );
}

float QtXmlWrapper::getparreal(const char *name,
Expand Down
5 changes: 3 additions & 2 deletions src/core/AutomatableModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "AutomationPattern.h"
#include "ControllerConnection.h"
#include "LocaleHelper.h"
#include "Mixer.h"
#include "ProjectJournal.h"

Expand Down Expand Up @@ -183,7 +184,7 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString&
if( node.isElement() )
{
changeID( node.toElement().attribute( "id" ).toInt() );
setValue( node.toElement().attribute( "value" ).toFloat() );
setValue( LocaleHelper::toFloat( node.toElement().attribute( "value" ) ) );
if( node.toElement().hasAttribute( "scale_type" ) )
{
if( node.toElement().attribute( "scale_type" ) == "linear" )
Expand All @@ -204,7 +205,7 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString&
if( element.hasAttribute( name ) )
// attribute => read the element's value from the attribute list
{
setInitValue( element.attribute( name ).toFloat() );
setInitValue( LocaleHelper::toFloat( element.attribute( name ) ) );
}
else
{
Expand Down
7 changes: 4 additions & 3 deletions src/core/AutomationPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "AutomationPatternView.h"
#include "AutomationTrack.h"
#include "LocaleHelper.h"
#include "Note.h"
#include "ProjectJournal.h"
#include "BBTrackContainer.h"
Expand Down Expand Up @@ -154,11 +155,11 @@ void AutomationPattern::setProgressionType(
void AutomationPattern::setTension( QString _new_tension )
{
bool ok;
float nt = _new_tension.toFloat( & ok );
float nt = LocaleHelper::toFloat(_new_tension, & ok);

if( ok && nt > -0.01 && nt < 1.01 )
{
m_tension = _new_tension.toFloat();
m_tension = nt;
}
}

Expand Down Expand Up @@ -595,7 +596,7 @@ void AutomationPattern::loadSettings( const QDomElement & _this )
if( element.tagName() == "time" )
{
m_timeMap[element.attribute( "pos" ).toInt()]
= element.attribute( "value" ).toFloat();
= LocaleHelper::toFloat(element.attribute("value"));
}
else if( element.tagName() == "object" )
{
Expand Down
38 changes: 4 additions & 34 deletions src/core/DataFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "Effect.h"
#include "embed.h"
#include "GuiApplication.h"
#include "LocaleHelper.h"
#include "PluginFactory.h"
#include "ProjectVersion.h"
#include "SongEditor.h"
Expand Down Expand Up @@ -65,37 +66,6 @@ DataFile::typeDescStruct



DataFile::LocaleHelper::LocaleHelper( Mode mode )
{
switch( mode )
{
case ModeLoad:
// set a locale for which QString::fromFloat() returns valid values if
// floating point separator is a comma - otherwise we would fail to load
// older projects made by people from various countries due to their
// locale settings
QLocale::setDefault( QLocale::German );
break;

case ModeSave:
// set default locale to C so that floating point decimals are rendered to
// strings with periods as decimal point instead of commas in some countries
QLocale::setDefault( QLocale::C );

default: break;
}
}



DataFile::LocaleHelper::~LocaleHelper()
{
// revert to original locale
QLocale::setDefault( QLocale::system() );
}




DataFile::DataFile( Type type ) :
QDomDocument( "lmms-project" ),
Expand Down Expand Up @@ -416,8 +386,8 @@ void DataFile::upgrade_0_2_1_20070501()
QDomElement el = list.item( i ).toElement();
if( el.attribute( "vol" ) != "" )
{
el.setAttribute( "vol", el.attribute(
"vol" ).toFloat() * 100.0f );
el.setAttribute( "vol", LocaleHelper::toFloat(
el.attribute( "vol" ) ) * 100.0f );
}
else
{
Expand Down Expand Up @@ -543,7 +513,7 @@ void DataFile::upgrade_0_2_1_20070508()
QDomElement el = list.item( i ).toElement();
if( el.hasAttribute( "vol" ) )
{
float value = el.attribute( "vol" ).toFloat();
float value = LocaleHelper::toFloat( el.attribute( "vol" ) );
value = roundf( value * 0.585786438f );
el.setAttribute( "vol", value );
}
Expand Down
4 changes: 0 additions & 4 deletions src/core/Song.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1016,8 +1016,6 @@ void Song::loadProject( const QString & fileName )

clearErrors();

DataFile::LocaleHelper localeHelper( DataFile::LocaleHelper::ModeLoad );

Engine::mixer()->requestChangeInModel();

// get the header information from the DOM
Expand Down Expand Up @@ -1173,8 +1171,6 @@ void Song::loadProject( const QString & fileName )
// only save current song as _filename and do nothing else
bool Song::saveProjectFile( const QString & filename )
{
DataFile::LocaleHelper localeHelper( DataFile::LocaleHelper::ModeSave );

DataFile dataFile( DataFile::SongProject );

m_tempoModel.saveSettings( dataFile, dataFile.head(), "bpm" );
Expand Down
Loading