diff --git a/CMakeLists.txt b/CMakeLists.txt
index 644d7f4..71fe340 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.16.0)
project(pipedal
- VERSION 1.2.37
+ VERSION 1.2.38
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
)
-set (DISPLAY_VERSION "v1.2.37beta4")
+set (DISPLAY_VERSION "v1.2.38beta5")
set (CMAKE_INSTALL_PREFIX "/usr/")
diff --git a/README.md b/README.md
index 81ffe65..24b232b 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,11 @@
-Download: v1.2.37 Beta4 Website: [https://rerdavies.github.io/pipedal](https://rerdavies.github.io/pipedal).
+Download: v1.2.38 Beta5 Website: [https://rerdavies.github.io/pipedal](https://rerdavies.github.io/pipedal).
-#### NEW version 1.2.37 Beta4 release, providing support for Raspberry Pi OS Bookworm. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
+#### NEW version 1.2.38 Beta5 release, providing support for Raspberry Pi OS Bookworm. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
diff --git a/docs/BuildPrerequisites.md b/docs/BuildPrerequisites.md
index d8411f5..0bc656f 100644
--- a/docs/BuildPrerequisites.md
+++ b/docs/BuildPrerequisites.md
@@ -26,7 +26,7 @@ Run the following commands to install dependent libraries required by the PiPeda
sudo apt install -y libasound2-dev jackd2 uuid-dev libxrandr-dev
sudo apt install -y authbind
sudo apt install -y libavahi-client-dev
- sudo apt install -y libnm-dev
+ sudo apt install -y libnm-dev libicu-dev
sudo apt install -y libsdbus-c++-dev libzip-dev
diff --git a/docs/Installing.md b/docs/Installing.md
index 7a0515d..7a381a3 100644
--- a/docs/Installing.md
+++ b/docs/Installing.md
@@ -13,17 +13,17 @@ page_icon: img/Install4.jpg
Download the most recent Debian (.deb) package for your platform:
-- [Raspberry Pi OS bookworm (64-bit) v1.2.37 Beta4](https://github.com/rerdavies/pipedal/releases/download/)
+- [Raspberry Pi OS bookworm (64-bit) v1.2.38 Beta5](https://github.com/rerdavies/pipedal/releases/download/)
- [Ubuntu/Raspberry Pi OS bullseyeye (64-bit) v1.2.31](https://github.com/rerdavies/pipedal/releases/download/v1.1.31/pipedal_1.1.31_arm64.deb)
-Version 1.2.37 has not yet been tested on Ubuntu or Raspberry Pi OS bullseye. On these platforms, we recommend that you use version 1.1.31.
+Version 1.2.38 has not yet been tested on Ubuntu or Raspberry Pi OS bullseye. On these platforms, we recommend that you use version 1.1.31.
Install the package by running
```
sudo apt update
cd ~/Downloads
- sudo apt-get install pipedal_1.2.37_arm64.deb
+ sudo apt-get install pipedal_1.2.38_arm64.deb
```
Adjust accordingly if you have downloaded v1.1.31.
diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index e0a64bc..de4668d 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -1,4 +1,9 @@
# Release Notes
+## Pipedal 1.2.38 Beta5
+
+Fixes:
+- PiPedal won't run on non-en-US locales.
+
## Pipedal 1.2.37 Beta4
You can now upload GuitarML Proteus models from the GuitarML project into TooB ML.
diff --git a/docs/download.md b/docs/download.md
index 2867647..a308f3d 100644
--- a/docs/download.md
+++ b/docs/download.md
@@ -4,17 +4,17 @@
Download the most recent Debian (.deb) package for your platform:
-- Raspberry Pi OS Bookworm (64-bit) v1.2.37 Beta4
+- Raspberry Pi OS Bookworm (64-bit) v1.2.38 Beta5
- Ubuntu 21.04 or Raspberry Pi OS bullseyeyeye (64-bit) v1.1.31
-v1.2.37 Beta4 is does not currently support Ubuntu 21.04, or older versions of Raspberry Pi OS.
+v1.2.38 Beta5 is does not currently support Ubuntu 21.04, or older versions of Raspberry Pi OS.
Install the package by running
```
sudo apt update
cd ~/Downloads
- sudo apt-get install ./pipedal_1.2.37_arm64.deb
+ sudo apt-get install ./pipedal_1.2.38_arm64.deb
```
Follow the instructions in [_Configuring PiPedal After Installation_](https://rerdavies.github.io/pipedal/Configuring.html) to complete the installation.
diff --git a/docs/index.md b/docs/index.md
index 5903571..d17e9cf 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,13 +1,13 @@
-v1.2.37
+v1.2.38
To download PiPedal, click [here](download.md).
-> NEW version 1.2.37 Beta4 release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
+> NEW version 1.2.38 Beta5 release. See the [release notes](https://rerdavies.github.io/pipedal/ReleaseNotes) for details.
Use your Raspberry Pi as a guitar effects pedal. Configure and control PiPedal with your phone or tablet.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6a23245..9aa027f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -133,6 +133,7 @@ endif()
set (PIPEDAL_SOURCES
WebServerConfig.cpp WebServerConfig.hpp
+ Locale.hpp Locale.cpp
Finally.hpp
ZipFile.cpp ZipFile.hpp
TemporaryFile.cpp TemporaryFile.hpp
@@ -204,7 +205,6 @@ set (PIPEDAL_SOURCES
AdminClient.hpp AdminClient.cpp
MidiBinding.hpp MidiBinding.cpp
PiPedalMath.hpp
- Locale.hpp Locale.cpp
Lv2EventBufferWriter.hpp Lv2EventBufferWriter.cpp
IpSubnet.hpp
PiPedalAlsa.hpp PiPedalAlsa.cpp
@@ -235,6 +235,9 @@ set (PIPEDAL_INCLUDES
)
set(PIPEDAL_LIBS libpipedald zip
+ icui18n
+ icuuc
+ icudata
pthread atomic stdc++fs asound avahi-common avahi-client systemd
${VST3_LIBRARIES}
${LILV_0_LIBRARIES}
diff --git a/src/ConfigMain.cpp b/src/ConfigMain.cpp
index 13c1d7f..3e2efbe 100644
--- a/src/ConfigMain.cpp
+++ b/src/ConfigMain.cpp
@@ -607,7 +607,6 @@ void SetVarPermissions(
if (fs::is_directory(path)) {
fs::permissions(path, directoryPermissions, fs::perm_options::replace);
for (const auto& entry : fs::recursive_directory_iterator(path)) {
- cout << " " << entry.path() << endl;
if (chown(entry.path().c_str(),uid,gid) != 0)
{
diff --git a/src/Locale.cpp b/src/Locale.cpp
index aced0d2..6caec02 100644
--- a/src/Locale.cpp
+++ b/src/Locale.cpp
@@ -23,43 +23,134 @@
#include
#include "Lv2Log.hpp"
-
+#include
+#include
+#include
+#include
+#include
+#include "ss.hpp"
+#include
// Must be UNICODE. Should reflect system locale. (.e.g en-US.UTF8, de-de.UTF8)
// This is correct for libstdc++; most probably not correct for Windows or CLANG. :-(
using namespace pipedal;
-static const char*getLocale(const char*localeEnvironmentVariable)
+
+std::string getCurrentLocale() {
+ std::string locale = setlocale(LC_ALL, nullptr);
+ if (locale.empty() || locale == "C") {
+ // If setlocale fails, try getting it from environment variables
+ const char* lang = getenv("LC_ALL");
+ if (lang) {
+ locale = lang;
+ } else {
+ // If LANG is not set, fall back to a default
+ lang = getenv("LC_COLLATE");
+ if (lang)
+ {
+ locale = lang;
+ } else{
+ lang = getenv("LANG");
+ if (lang) {
+ locale = lang;
+ } else {
+ locale = "en_US";
+ }
+ }
+ }
+ }
+ // Extract just the language and country code
+ size_t dot_pos = locale.find('.');
+ if (dot_pos != std::string::npos) {
+ locale = locale.substr(0, dot_pos);
+ }
+ return locale;
+}
+
+Collator::~Collator() {
+
+}
+
+class LocaleImpl;
+
+class CollatorImpl : public Collator {
+public:
+ CollatorImpl(std::shared_ptr LocaleImpl,icu::Locale &locale);
+ ~CollatorImpl();
+
+ virtual int Compare(const std::string &left, const std::string&right);
+private:
+ icu::Collator* collator = nullptr;
+ std::shared_ptr localeImpl;
+};
+
+CollatorImpl::~CollatorImpl()
{
- const char*result = getenv(localeEnvironmentVariable);
- if (result == nullptr)
- {
- result = getenv("LC_ALL");
- }
+ delete collator;
+ localeImpl = nullptr;
+}
+CollatorImpl::CollatorImpl(std::shared_ptr localeImpl, icu::Locale &locale)
+:localeImpl(localeImpl)
+{
+ UErrorCode status = U_ZERO_ERROR;
- if (result == nullptr) {
- result = "en_US.UTF-8";
+ this->collator = icu::Collator::createInstance(locale, status);
+
+ if (U_FAILURE(status)) {
+ throw std::runtime_error(SS("Failed to create collator: " << u_errorName(status)));
}
- std::stringstream s;
- s << "Locale: " << result;
- Lv2Log::error(s.str());
- return result;
+}
+
+int CollatorImpl::Compare(const std::string &left, const std::string&right) {
+ return collator->compare(left.c_str(),right.c_str());
+}
+Locale::ptr g_instance;
+
+class LocaleImpl: public Locale, public std::enable_shared_from_this {
+public:
+ LocaleImpl();
+ virtual const std::string &CurrentLocale() const ;
+ virtual Collator::ptr GetCollator();
+private:
+ std::unique_ptr locale;
+ std::string currentLocale;
+};
+
+LocaleImpl::LocaleImpl()
+{
+ currentLocale = getCurrentLocale();
+ locale = std::make_unique(currentLocale.c_str());
+}
+const std::string &LocaleImpl::CurrentLocale() const
+{
+ return currentLocale;
}
-void Locale::setDefaultLocale() {
- const char* locale = getLocale("LC_ALL");
- try {
- setlocale(LC_ALL,locale);
- } catch (const std::exception&)
- {
- std::stringstream s;
- s << "Failed to set default locale (" << locale << "). Defaulting to en_US.";
- Lv2Log::error(s.str());
-
- std::setlocale(LC_ALL,"en_US.UTF-8");
- }
+Collator::ptr LocaleImpl::GetCollator(){
+ auto pThis = shared_from_this();
+ return std::shared_ptr(new CollatorImpl(pThis,*locale));
}
-const std::collate& Locale::collation() { return std::use_facet >(std::locale()); }
+
+static std::mutex createMutex;
+
+Locale::~Locale()
+{
+
+}
+Locale::ptr Locale::g_instance;
+
+Locale::ptr Locale::GetInstance()
+{
+ std::lock_guard lock { createMutex};
+
+ if (g_instance)
+ {
+ return g_instance;
+ }
+ g_instance = std::make_shared();
+ return g_instance;
+}
+
diff --git a/src/Locale.hpp b/src/Locale.hpp
index 5cce1f2..9d0ae1b 100644
--- a/src/Locale.hpp
+++ b/src/Locale.hpp
@@ -19,14 +19,34 @@
#pragma once
-#include
+#include
+#include
namespace pipedal {
-
- class Locale {
+ class Collator {
public:
- static void setDefaultLocale();
+ using ptr = std::shared_ptr;
+ virtual int Compare(const std::string &left, const std::string&right) = 0;
+ virtual ~Collator();
+ };
+ class Locale {
+ protected:
+ Locale() { }
+ public:
+ virtual ~Locale();
+ // no copy, no move
+ Locale(const Locale&) = delete;
+ Locale(Locale&&) = delete;
+ Locale&operator =(const Locale&) = delete;
+ Locale&operator =(Locale&&) = delete;
+
+ using ptr = std::shared_ptr;
- static const std::collate& collation();
+ static ptr GetInstance();
+
+ virtual const std::string &CurrentLocale() const = 0;
+ virtual Collator::ptr GetCollator() = 0;
+ private:
+ static ptr g_instance;
};
}
diff --git a/src/PluginHost.cpp b/src/PluginHost.cpp
index 3cb47a2..b069caf 100644
--- a/src/PluginHost.cpp
+++ b/src/PluginHost.cpp
@@ -21,7 +21,7 @@
#include "PluginHost.hpp"
#include
#include
-#include
+#include "Locale.hpp"
#include
#include "Lv2Log.hpp"
#include
@@ -461,16 +461,16 @@ void PluginHost::Load(const char *lv2Path)
Lv2Log::info("lilv: " + s);
}
- const auto &collation = std::use_facet>(std::locale());
- auto compare = [&collation](
+ auto collator = Locale::GetInstance()->GetCollator();
+ auto compare = [&collator](
const std::shared_ptr &left,
const std::shared_ptr &right)
{
const char *pb1 = left->name().c_str();
const char *pb2 = right->name().c_str();
- return collation.compare(
- pb1, pb1 + left->name().size(),
- pb2, pb2 + right->name().size()) < 0;
+ return collator->Compare(
+ left->name(),right->name())
+ < 0;
};
std::sort(this->plugins_.begin(), this->plugins_.end(), compare);
diff --git a/src/Storage.cpp b/src/Storage.cpp
index 24079a6..d593afb 100644
--- a/src/Storage.cpp
+++ b/src/Storage.cpp
@@ -18,6 +18,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pch.h"
+#include "Locale.hpp"
#include "Storage.hpp"
#include "AudioConfig.hpp"
#include "PiPedalException.hpp"
@@ -40,7 +41,6 @@ const char *BANKS_FILENAME = "index.banks";
#define USER_SETTINGS_FILENAME "userSettings.json";
Storage::Storage()
-: locale("en_US.UTF-8")
{
SetConfigRoot("~/var/Config");
SetDataRoot("~/var/PiPedal");
@@ -1525,9 +1525,10 @@ std::vector Storage::GetFileList(const UiFileProperty &fileProperty
}
// sort lexicographically
+ auto collator = Locale::GetInstance()->GetCollator();
- std::sort(result.begin(), result.end(), [this](const std::string&left,const std::string&right) {
- return this->locale(left,right) < 0;
+ std::sort(result.begin(), result.end(), [&collator](const std::string&left,const std::string&right) {
+ return collator->Compare(left,right) < 0;
});
return result;
}
@@ -1606,12 +1607,14 @@ std::vector Storage::GetFileList2(const std::string &relativePath,con
// sort lexicographically
- std::sort(result.begin(), result.end(),[this](const FileEntry&l, const FileEntry&r) {
+ auto collator = Locale::GetInstance()->GetCollator();
+
+ std::sort(result.begin(), result.end(),[&collator](const FileEntry&l, const FileEntry&r) {
if (l.isDirectory_ != r.isDirectory_)
{
return l.isDirectory_ > r.isDirectory_;
}
- return this->locale(l.filename_,r.filename_);
+ return collator->Compare(l.filename_,r.filename_) < 0;
});
return result;
@@ -1813,10 +1816,11 @@ void Storage::FillSampleDirectoryTree(FilePropertyDirectoryTree*node, const std:
node->children_.push_back(std::move(childTree));
}
}
+ auto collator = Locale::GetInstance()->GetCollator();
std::sort(node->children_.begin(),node->children_.end(),
- [this](const FilePropertyDirectoryTree::ptr&left,const FilePropertyDirectoryTree::ptr&right)
+ [&collator](const FilePropertyDirectoryTree::ptr&left,const FilePropertyDirectoryTree::ptr&right)
{
- return this->locale(left->directoryName_,right->directoryName_);
+ return collator->Compare(left->directoryName_,right->directoryName_) < 0;
});
}
FilePropertyDirectoryTree::ptr Storage::GetFilePropertydirectoryTree(const UiFileProperty&uiFileProperty) const
diff --git a/src/Storage.hpp b/src/Storage.hpp
index deaea9c..514686b 100644
--- a/src/Storage.hpp
+++ b/src/Storage.hpp
@@ -30,7 +30,6 @@
#include "WifiDirectConfigSettings.hpp"
#include "FileEntry.hpp"
#include