Precached images. ToobTuner. key additions.

This commit is contained in:
Robin Davies
2022-02-23 04:29:21 -05:00
parent ac51296782
commit f677b8b608
24 changed files with 589 additions and 137 deletions
+7 -3
View File
@@ -754,7 +754,7 @@ public:
#else
xxx; // TODO!
#endif
int underrunMessagesGiven = 0;
try
{
@@ -787,8 +787,12 @@ public:
uint64_t underruns = this->underruns;
if (underruns != lastUnderrunCount)
{
Lv2Log::info("Jack - Underrun count: %lu", (unsigned long)underruns);
lastUnderrunCount = underruns;
if (underrunMessagesGiven < 60) // limit how much log file clutter we generate.
{
Lv2Log::info("Jack - Underrun count: %lu", (unsigned long)underruns);
lastUnderrunCount = underruns;
++underrunMessagesGiven;
}
}
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += pollRateS;
+29
View File
@@ -33,6 +33,7 @@
#include "lv2/urid.lv2/urid.h"
#include "lv2.h"
#include "lv2/atom.lv2/atom.h"
#include "lv2/time/time.h"
#include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h"
#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
#include "lv2/lv2plug.in/ns/ext/port-props/port-props.h"
@@ -40,8 +41,10 @@
#include "lv2/lv2plug.in/ns/ext/port-groups/port-groups.h"
#include <fstream>
#include "PiPedalException.hpp"
#include "Locale.hpp"
using namespace pipedal;
#define MAP_CHECK() \
@@ -115,6 +118,12 @@ void Lv2Host::LilvUris::Initialize(LilvWorld*pWorld)
symbolUri = lilv_new_uri(pWorld, LV2_CORE__symbol);
nameUri = lilv_new_uri(pWorld, LV2_CORE__name);
time_Position = lilv_new_uri(pWorld, LV2_TIME__Position);
time_barBeat = lilv_new_uri(pWorld, LV2_TIME__barBeat);
time_beatsPerMinute = lilv_new_uri(pWorld, LV2_TIME__beatsPerMinute);
time_speed = lilv_new_uri(pWorld, LV2_TIME__speed);
}
void Lv2Host::LilvUris::Free()
@@ -137,6 +146,11 @@ void Lv2Host::LilvUris::Free()
symbolUri.Free();
nameUri.Free();
time_Position.Free();
time_barBeat.Free();
time_beatsPerMinute.Free();
time_speed.Free();
}
static std::string nodeAsString(const LilvNode *node)
@@ -398,10 +412,12 @@ void Lv2Host::Load(const char *lv2Path)
{
Lv2Log::debug("Plugin %s (%s) skipped. (Has CV ports).", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
}
#if !SUPPORT_MIDI
else if (pluginInfo->plugin_class() == LV2_MIDI_PLUGIN)
{
Lv2Log::debug("Plugin %s (%s) skipped. (MIDI Plugin).", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
}
#endif
else if (!pluginInfo->is_valid())
{
auto &ports = pluginInfo->ports();
@@ -439,6 +455,16 @@ void Lv2Host::Load(const char *lv2Path)
Lv2PluginUiInfo info(this, plugin.get());
if (plugin->is_valid())
{
#if SUPPORT_MIDI
if (info.audio_inputs() == 0 && !info.has_midi_input())
{
Lv2Log::debug("Plugin %s (%s) skipped. No inputs.", plugin->name().c_str(), plugin->uri().c_str());
}
else if (info.audio_outputs() == 0 && !info.has_midi_output())
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
}
#else
if (info.audio_inputs() == 0)
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio inputs.", plugin->name().c_str(), plugin->uri().c_str());
@@ -447,6 +473,7 @@ void Lv2Host::Load(const char *lv2Path)
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
}
#endif
else
{
ui_plugins_.push_back(std::move(info));
@@ -718,6 +745,7 @@ Lv2PortInfo::Lv2PortInfo(Lv2Host *host, const LilvPlugin *plugin, const LilvPort
is_cv_port_ = is_a(host, LV2_CORE__CVPort);
supports_midi_ = lilv_port_supports_event(plugin, pPort, host->lilvUris.midiEventNode);
supports_time_position_ = lilv_port_supports_event(plugin, pPort, host->lilvUris.time_Position);
NodeAutoFree designationValue = lilv_port_get(plugin, pPort, host->lilvUris.designationNode);
designation_ = nodeAsString(designationValue);
@@ -1096,6 +1124,7 @@ json_map::storage_type<Lv2PortInfo> Lv2PortInfo::jmap{{
json_map::reference("is_valid", &Lv2PortInfo::is_valid_),
json_map::reference("supports_midi", &Lv2PortInfo::supports_midi_),
json_map::reference("supports_time_position", &Lv2PortInfo::supports_time_position_),
json_map::reference("port_group", &Lv2PortInfo::port_group_),
json_map::reference("is_logarithmic", &Lv2PortInfo::is_logarithmic_),
+26
View File
@@ -208,6 +208,7 @@ private:
bool is_valid_ = false;
bool supports_midi_ = false;
bool supports_time_position_ = false;
bool is_logarithmic_ = false;
int display_priority_ = -1;
int range_steps_ = 0;
@@ -267,6 +268,7 @@ public:
LV2_PROPERTY_GETSET_SCALAR(is_cv_port);
LV2_PROPERTY_GETSET_SCALAR(is_valid);
LV2_PROPERTY_GETSET_SCALAR(supports_midi);
LV2_PROPERTY_GETSET_SCALAR(supports_time_position);
LV2_PROPERTY_GETSET_SCALAR(is_logarithmic);
LV2_PROPERTY_GETSET_SCALAR(display_priority);
LV2_PROPERTY_GETSET_SCALAR(range_steps);
@@ -381,6 +383,24 @@ public:
}
return false;
}
bool hasMidiInput() const {
for (size_t i = 0; i < ports_.size(); ++i)
{
if (ports_[i]->is_atom_port() && ports_[i]->supports_midi() && ports_[i]->is_input())
{
return true;
}
}
}
bool hasMidiOutput() const {
for (size_t i = 0; i < ports_.size(); ++i)
{
if (ports_[i]->is_atom_port() && ports_[i]->supports_midi() && ports_[i]->is_output())
{
return true;
}
}
}
public:
@@ -598,6 +618,12 @@ private:
LilvNodePtr symbolUri;
LilvNodePtr nameUri;
LilvNodePtr time_Position;
LilvNodePtr time_barBeat;
LilvNodePtr time_beatsPerMinute;
LilvNodePtr time_speed;
};
LilvUris lilvUris;
+7 -1
View File
@@ -36,6 +36,7 @@ class PiPedalConfiguration
private:
std::string lv2_path_ = "/usr/lib/lv2:/usr/local/lib/lv2";
std::filesystem::path docRoot_;
std::filesystem::path webRoot_;
std::string local_storage_path_;
bool mlock_ = true;
std::vector<std::string> reactServerAddresses_ = {"*:5000"};
@@ -52,7 +53,10 @@ public:
std::filesystem::path GetConfigFilePath() const {
return docRoot_ / "config.jason";
}
void Load(std::filesystem::path path) {
const std::filesystem::path& GetWebRoot() const {
return webRoot_;
}
void Load(const std::filesystem::path& path, const std::filesystem::path&webRoot) {
std::filesystem::path configPath = path / "config.json";
if (!std::filesystem::exists(configPath))
{
@@ -68,6 +72,8 @@ public:
json_reader reader(f);
reader.read(this);
docRoot_ = path;
webRoot_ = webRoot;
}
const std::filesystem::path &GetDocRoot() const { return docRoot_; }
+7 -2
View File
@@ -113,7 +113,7 @@ void PiPedalModel::LoadLv2PluginInfo(const PiPedalConfiguration&configuration)
void PiPedalModel::Load(const PiPedalConfiguration &configuration)
{
this->webRoot = configuration.GetWebRoot();
this->jackServerSettings.ReadJackConfiguration();
@@ -1164,4 +1164,9 @@ void PiPedalModel::cancelListenForAtomOutputs(int64_t clientId, int64_t clientHa
std::vector<AlsaDeviceInfo> PiPedalModel::GetAlsaDevices()
{
return this->alsaDevices.GetAlsaDevices();
}
}
const std::filesystem::path& PiPedalModel::GetWebRoot() const
{
return webRoot;
}
+2 -1
View File
@@ -92,6 +92,7 @@ private:
std::unique_ptr<JackHost> jackHost;
JackConfiguration jackConfiguration;
std::shared_ptr<Lv2PedalBoard> lv2PedalBoard;
std::filesystem::path webRoot;
std::vector<IPiPedalModelSubscriber*> subscribers;
@@ -219,7 +220,7 @@ public:
void cancelListenForAtomOutputs(int64_t clientId, int64_t clientHandle);
std::vector<AlsaDeviceInfo> GetAlsaDevices();
const std::filesystem::path& GetWebRoot() const;
};
} // namespace pipedal.
+21 -1
View File
@@ -34,6 +34,7 @@
#include "WifiChannels.hpp"
#include "SysExec.hpp"
#include "PiPedalAlsa.hpp"
#include <filesystem>
using namespace std;
using namespace pipedal;
@@ -344,6 +345,7 @@ private:
std::recursive_mutex writeMutex;
PiPedalModel &model;
static std::atomic<uint64_t> nextClientId;
std::string imageList;
uint64_t clientId;
// pedalboard is mutable and not thread-safe.
@@ -390,6 +392,19 @@ public:
PiPedalSocketHandler(PiPedalModel &model)
: model(model), clientId(++nextClientId)
{
std::stringstream imageList;
const std::filesystem::path& webRoot = model.GetWebRoot() / "img";
bool firstTime = true;
for (const auto&entry: std::filesystem::directory_iterator(webRoot))
{
if (!firstTime)
{
imageList << ";";
}
firstTime = false;
imageList << entry.path().filename().string();
}
this->imageList = imageList.str();
}
private:
@@ -1067,7 +1082,7 @@ public:
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
activeVuSubscriptions.push_back(VuSubscription{subscriptionHandle, instanceId});
}
this->Reply(replyTo, "addVuSubscriptin", subscriptionHandle);
this->Reply(replyTo, "addVuSubscription", subscriptionHandle);
}
else if (message == "removeVuSubscription")
{
@@ -1087,6 +1102,11 @@ public:
}
model.removeVuSubscription(subscriptionHandle);
}
else if (message == "imageList")
{
this->Reply(replyTo, "imageList", imageList);
}
else
{
Lv2Log::error("Unknown message received: %s", message.c_str());
+47 -13
View File
@@ -416,6 +416,9 @@ void json_reader::skip_property()
int c = is_.peek();
switch (c)
{
case -1:
throw_format_error("Premature end of file.");
break;
case '[':
skip_array();
break;
@@ -442,8 +445,10 @@ void json_reader::skip_string()
consume('"');
while (true)
{
char c;
int c;
c = get();
if (c == -1) throw_format_error("Premature end of file.");
if (c == '\"')
{
if (peek() == '\"')
@@ -463,27 +468,54 @@ void json_reader::skip_string()
void json_reader::skip_number()
{
skip_whitespace();
char c;
while (true)
int c;
if (is_.peek() == '-')
{
int ic = is_.peek();
if (ic == -1)
break;
if (is_whitespace((char)ic))
get();
}
if (!std::isdigit(is_.peek()))
{
throw_format_error("Expecting a number.");
}
while (std::isdigit(is_.peek()))
{
get();
}
if (is_.peek() == '.')
{
get();
}
while (std::isdigit(is_.peek()))
{
get();
}
c = is_.peek();
if (c == 'e' || c == 'E')
{
get();
c = is_.peek();
if (c == '+' || c == 'i')
{
break;
get();
}
c = get();
while (std::isdigit(is_.peek()))
{
get();
}
}
}
void json_reader::skip_array()
{
char c;
int c;
consume('[');
while (true)
{
if (peek() == ']')
c = peek();
if (c == -1) throw_format_error("Premature end of file.");
if (c == ']')
{
c = get();
break;
@@ -499,11 +531,13 @@ void json_reader::skip_array()
void json_reader::skip_object()
{
char c;
int c;
consume('{');
while (true)
{
if (peek() == '}')
c = peek();
if (c == -1) throw_format_error("Premature end of file.");
if (c == '}')
{
c = get();
break;
+48 -5
View File
@@ -27,6 +27,7 @@
#include <sstream>
#include "HtmlHelper.hpp"
#include <cctype>
#include <cmath>
#include "PiPedalException.hpp"
@@ -243,6 +244,7 @@ class json_writer {
public:
const char*CRLF;
private:
bool allowNaN_ = true;
std::ostream &os;
int indent_level;
bool compressed;
@@ -276,13 +278,17 @@ public:
os << text;
}
using string_view = boost::string_view;
json_writer(std::ostream &os, bool compressed = false)
json_writer(std::ostream &os, bool compressed = false, bool allowNaN = true)
: os(os)
, compressed(compressed)
, allowNaN_(allowNaN)
, indent_level(0)
{
this->CRLF = compressed? "" : "\r\n";
}
bool allowNaN() const { return allowNaN_; }
void allowNaN(bool allow) { allowNaN_ = allow; }
void write(long long value)
{
os << value;
@@ -342,11 +348,21 @@ public:
}
void write(float f)
{
os << std::setprecision(std::numeric_limits<float>::max_digits10) << f; // round-trip format
if (allowNaN_ && (std::isnan(f) || std::isinf(f)))
{
os << "NaN";
} else {
os << std::setprecision(std::numeric_limits<float>::max_digits10) << f; // round-trip format
}
}
void write(double f)
{
os << std::setprecision(std::numeric_limits<double>::max_digits10) << f; // round-trip format
if (allowNaN_ && (std::isnan(f) || std::isinf(f)))
{
os << "NaN";
} else {
os << std::setprecision(std::numeric_limits<double>::max_digits10) << f; // round-trip format
}
}
template <typename T> void write(const std::vector<T> &value)
@@ -526,20 +542,26 @@ public:
class json_reader {
private:
std::istream &is_;
const uint16_t UTF16_SURROGATE_1_BASE = 0xD800U;
const uint16_t UTF16_SURROGATE_2_BASE = 0xDC00U;
const uint16_t UTF16_SURROGATE_MASK = 0x3FFU;
bool allowNaN_ = true;
public:
json_reader(std::istream &input)
json_reader(std::istream &input, bool allowNaN = true)
: is_(input)
{
this->allowNaN_ = allowNaN;
}
bool allowNaN() const { return allowNaN_;}
void allowNaN(bool allow) { allowNaN_ = allow; }
private:
void throw_format_error(const char*error);
@@ -719,11 +741,32 @@ public:
void read(float*value) {
skip_whitespace();
if (allowNaN_)
{
if (peek() == 'N')
{
consumeToken("NaN","Expecting a number.");
*value = std::nanf("");
return;
}
}
is_ >> *value;
if (is_.fail()) throw PiPedalException("Invalid format.");
}
void read(double*value) {
skip_whitespace();
if (allowNaN_)
{
if (peek() == 'N')
{
consumeToken("NaN","Expecting a number.");
*value = std::nan("");
return;
}
}
is_ >> *value;
if (is_.fail()) throw PiPedalException("Invalid format.");
}
+1 -1
View File
@@ -480,7 +480,7 @@ int main(int argc, char *argv[])
PiPedalConfiguration configuration;
try
{
configuration.Load(doc_root);
configuration.Load(doc_root,web_root);
}
catch (const std::exception &e)
{
+4
View File
@@ -22,6 +22,10 @@
// Diagnostic type used to report calculated type T in an error message.
template <typename T> class TypeDisplay;
#ifndef SUPPORT_MIDI // currently, only whether midi plugins can be loaded. No routing or handling implemented (yet).
#define SUPPORT_MIDI 0
#endif
#include <mutex>
#include <string>