Skip to content

Commit

Permalink
Merge branch 'preferences' and live PCM driver updates
Browse files Browse the repository at this point in the history
* preferences:
  UI: util.js: call prop->ident()
  ASE: shorten Parameter method ident()
  ASE: strings: add fallback to string_option_find(), remove string_option_get()
  ASE: testing.cc: use string_option_find_value()
  ASE: processor.cc: use string_option_find()
  ASE: cxxaux.cc: use ase_fatal_warnings
  ASE: main: remove feature toggles, use ase_fatal_warnings
  ASE: utils: export ase_fatal_warnings
  ASE: utils.cc: base debug key checks on string_option_find_value()
  ASE: strings: base option search on string_option_find_value() (without malloc)
  ASE: project: create_properties: use property_bag() and Prop
  ASE: clapdevice.cc: use parameter_guess_nick()
  ASE: gadget: add property_bag() and create_properties()
  UI: b/preferencesdialog.vue: edit everything with Shift+Ctrl+Alt+Click [Close]
  UI: b/preferencesdialog.vue: fetch + edit only selected PCM + MIDI preferences
  UI: b/objecteditor.js: fix blurb and descr bubbles
  UI: index.html, eslintrc.js: allow _("for translation") markup
  UI: util.js: rename extended Property descr() (abbreviate)
  UI: b/choiceinput.js: treat choice property as string
  UI: b/preferencesdialog.vue: special case driver.pcm.devid
  UI: b/objecteditor.js: rename internal function on xprop
  UI: b/contextmenu.js: support focus_uri
  ASE: engine.cc: add preferences for up to 4 MIDI controllers
  ASE: engine.cc: cache PCM driver live listing for ca half a second
  ASE: engine: change PCM driver when preferences change
  ASE: engine.cc: add audio.synth_latency Preference
  ASE: driver*: allow to query all PcmConfig values from drivers
  ASE: api.hh, server: remove all old preference handling
  ASE: api.hh, server: add Server.list_preferences()
  ASE: properties: add Preference classes and majorly simplify Property impls
	* Remove obsolete structures and aux constructors
	* Add getter/setter lister for enumeration types
	* Add PropertyBag - a helper to simplify property registrations
	* Add small PropertyImpl based on ParameterProperty
	* Add generic Preference class, useful for static initialization
	* Remove property nick guessing
	* Add global Preference setting list based on Parameter
	* Implement saving/loading preferences from anklangrc
	* Auto save preference changes after maybe half a second
	* Ensure that Preference names follow NCName syntax
  ASE: defs.hh: add PropertyImpl
  ASE: api.hh: rename Property.descr() (abbreviate)
  ASE: api.hh, server: provide access_preference() instead of access_prefs()
  ASE: api.hh: add constexpr GUIONLY, STORAGE, STANDARD to avoid C++ SIOF
  ASE: main.cc: save/load preferences unless --norc is given
  ASE: processor: use Parameter instead of the old ParamInfo
  ASE: parameter: add Parameter, ParameterProperty and parameter_guess_nick()
	* Implement Parameter{} with Param{} as initializer
	* Add constrain, normalize and text conversions
	* Implement simple ParameterProperty abstract base class
	* Support callback function to query parameter choices
	* In set_value: constrain Value according to parameter range
	* Use variants for flexible initilizers
	* Treat choice parameters as text
	* Match choices via normalized Damerau-Levenshtein distance
	* Add parameter_guess_nick() (former on property_guess_nick).
  ASE: value.hh: add Value::is_string()
  ASE: object.cc: allow NCName as event detail, to support preference identifiers
  ASE: defs.hh: declare Preference
  ASE: strings: add kvpairs_search()
  ASE: strings: define and use ASE_STRING_SET_ASCII_ALNUM and _LOWER_ALNUM
  ASE: unicode.cc: add missing docs
  ASE: unicode: add string_to_ncname() and string_is_ncname()
  ASE: levenshtein: compute (un)restricted Damerau-Levenshtein string distances
  ASE: defs.hh: add F32EPS and F32MAX
  ASE: memory.hh: declare CStringS
  ASE: loop: add exec_once()
  ASE: cxxaux.hh: add ASE_ASSERT_ALWAYS()
  MISC: package.json.in: reduce wait delay for rebuilds

Signed-off-by: Tim Janik <[email protected]>
  • Loading branch information
tim-janik committed Oct 16, 2023
2 parents 3a7c2d3 + cbdc9fc commit c7ece44
Show file tree
Hide file tree
Showing 48 changed files with 2,061 additions and 1,643 deletions.
41 changes: 8 additions & 33 deletions ase/api.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
namespace Ase {

// == Property hint constants ==
extern const String STORAGE; // ":r:w:S:";
extern const String STANDARD; // ":r:w:S:G:";
constexpr const char GUIONLY[] = ":G:r:w:"; ///< GUI READABLE WRITABLE
constexpr const char STORAGE[] = ":S:r:w:"; ///< STORAGE READABLE WRITABLE
constexpr const char STANDARD[] = ":S:G:r:w:"; ///< STORAGE GUI READABLE WRITABLE

/// Common base type for polymorphic classes managed by `std::shared_ptr<>`.
class SharedBase : public virtual VirtualBase,
Expand Down Expand Up @@ -133,14 +134,14 @@ class Property : public virtual Emittable {
protected:
virtual ~Property () = 0;
public:
virtual String identifier () = 0; ///< Unique name (per owner) of this Property.
virtual String ident () = 0; ///< Unique name (per owner) of this Property.
virtual String label () = 0; ///< Preferred user interface name.
virtual String nick () = 0; ///< Abbreviated user interface name, usually not more than 6 characters.
virtual String unit () = 0; ///< Units of the values within range.
virtual String hints () = 0; ///< Hints for parameter handling.
virtual String group () = 0; ///< Group name for parameters of similar function.
virtual String blurb () = 0; ///< Short description for user interface tooltips.
virtual String description () = 0; ///< Elaborate description for help dialogs.
virtual String descr () = 0; ///< Elaborate description for help dialogs.
virtual double get_min () = 0; ///< Get the minimum property value, converted to double.
virtual double get_max () = 0; ///< Get the maximum property value, converted to double.
virtual double get_step () = 0; ///< Get the property value stepping, converted to double.
Expand All @@ -155,32 +156,6 @@ public:
virtual ChoiceS choices () = 0; ///< Enumerate choices for choosable properties.
};

// Preferences
struct Preferences {
// Synthesis Settings
String pcm_driver; ///< Driver and device to be used for PCM input and output.
int32 synth_latency = 5; ///< Processing duration between input and output of a single sample, smaller values increase CPU load.
int32 synth_mixing_freq = 48000; ///< Unused, synthesis mixing frequency is always 48000 Hz.
int32 synth_control_freq = 1500; ///< Unused frequency setting.
// MIDI
String midi_driver_1; ///< Driver and device to be used for MIDI input and output.
String midi_driver_2;
String midi_driver_3;
String midi_driver_4;
bool invert_sustain = false;
// Default Values
String author_default; ///< Default value for 'Author' fields.
String license_default; ///< Default value for 'License' fields.
String sample_path; ///< Search path of directories, seperated by ";", used to find audio samples.
String effect_path; ///< Search path of directories, seperated by ";", used to find effect files.
String instrument_path; ///< Search path of directories, seperated by ";", used to find instrument files.
String plugin_path; ///< Search path of directories, seperated by \";\", used to find plugins.
///< This path is searched for in addition to the standard plugin location on this system.
private:
PropertyS access_properties (const EventHandler&); ///< Retrieve handles for all properties.
friend class ServerImpl;
};

/// Base type for classes with Property interfaces.
class Object : public virtual Emittable {
protected:
Expand Down Expand Up @@ -394,9 +369,9 @@ public:
virtual uint64 user_note (const String &text, const String &channel = "misc", UserNote::Flags flags = UserNote::TRANSIENT, const String &rest = "") = 0;
virtual bool user_reply (uint64 noteid, uint r) = 0;
virtual bool broadcast_telemetry (const TelemetrySegmentS &segments,
int32 interval_ms) = 0; ///< Broadcast telemetry memory segments to the current Jsonipc connection.
// preferences
virtual PropertyS access_prefs () = 0; ///< Retrieve property handles for Preferences fields.
int32 interval_ms) = 0; ///< Broadcast telemetry memory segments to the current Jsonipc connection.
virtual StringS list_preferences () = 0; ///< Retrieve a list of all preference identifiers.
virtual PropertyP access_preference (const String &ident) = 0; ///< Retrieve property handle for a Preference identifier.
// projects
virtual ProjectP last_project () = 0; ///< Retrieve the last created project.
virtual ProjectP create_project (String projectname) = 0; ///< Create a new project (name is modified to be unique if necessary.
Expand Down
30 changes: 15 additions & 15 deletions ase/clapdevice.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ struct ClapPropertyImpl : public Property, public virtual EmittableImpl {
String ident_, label_, module_;
double min_value = NAN, max_value = NAN, default_value = NAN;
public:
String identifier () override { return ident_; }
String label () override { return label_; }
String nick () override { return property_guess_nick (label_); }
String unit () override { return ""; }
String hints () override { return ClapParamInfo::hints_from_param_info_flags (flags); }
String group () override { return module_; }
String blurb () override { return ""; }
String description () override { return ""; }
double get_min () override { return min_value; }
double get_max () override { return max_value; }
double get_step () override { return is_stepped() ? 1 : 0; }
bool is_numeric () override { return true; }
bool is_stepped () { return strstr (hints().c_str(), ":stepped:"); }
void reset () override { set_value (default_value); }
ClapPropertyImpl (ClapDeviceImplP device, const ClapParamInfo info) :
String ident () override { return ident_; }
String label () override { return label_; }
String nick () override { return parameter_guess_nick (label_); }
String unit () override { return ""; }
String hints () override { return ClapParamInfo::hints_from_param_info_flags (flags); }
String group () override { return module_; }
String blurb () override { return ""; }
String descr () override { return ""; }
double get_min () override { return min_value; }
double get_max () override { return max_value; }
double get_step () override { return is_stepped() ? 1 : 0; }
bool is_numeric () override { return true; }
bool is_stepped () { return strstr (hints().c_str(), ":stepped:"); }
void reset () override { set_value (default_value); }
ClapPropertyImpl (ClapDeviceImplP device, const ClapParamInfo info) :
device_ (device)
{
param_id = info.param_id;
Expand Down
4 changes: 2 additions & 2 deletions ase/cxxaux.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
#include "cxxaux.hh"
#include "main.hh" // main_config
#include "utils.hh" // ase_fatal_warnings
#include "backtrace.hh"
#include <cxxabi.h> // abi::__cxa_demangle
#include <signal.h>
Expand Down Expand Up @@ -45,7 +45,7 @@ assertion_failed (const std::string &msg, const char *file, int line, const char
ASE_PRINT_BACKTRACE (__FILE__, __LINE__, __func__);
else if (debug_key_enabled ("break"))
breakpoint();
if (main_config.fatal_warnings)
if (ase_fatal_warnings)
raise (SIGQUIT);
}

Expand Down
3 changes: 3 additions & 0 deletions ase/cxxaux.hh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ using VoidF = std::function<void()>;
/// Like ASE_ASSERT_WARN(), enabled if expensive `expr` are allowed.
#define ASE_ASSERT_PARANOID(expr) do { if (ASE_ISLIKELY (expr)) break; ::Ase::assertion_failed (#expr); } while (0)

/// Return from the current function if `expr` evaluates to false and issue an assertion warning.
#define ASE_ASSERT_ALWAYS(expr, ...) do { if (ASE_ISLIKELY (expr)) break; ::Ase::assertion_failed (#expr); __builtin_trap(); } while (0)

/// Delete copy ctor and assignment operator.
#define ASE_CLASS_NON_COPYABLE(ClassName) \
/*copy-ctor*/ ClassName (const ClassName&) = delete; \
Expand Down
6 changes: 5 additions & 1 deletion ase/defs.hh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ static constexpr uint32_t U32MAX = +4294967295u; // 2^32-1
static constexpr int32_t I31MAX = +2147483647; // 2^31-1
static constexpr int32_t I31MIN = -2147483648; // -2^31
static constexpr float M23MAX = 16777216; // 2^(1+23); IEEE-754 Float Mantissa maximum
static constexpr float F32EPS = 5.9604644775390625e-08; // 2^-24, round-off error at 1.0
static constexpr float F32MAX = 3.40282347e+38; // 7f7fffff, 2^128 * (1 - F32EPS)
static constexpr double M52MAX = 9007199254740992; // 2^(1+52); IEEE-754 Double Mantissa maximum
static constexpr double D64MAX = 1.7976931348623157e+308; // 0x7fefffff ffffffff, IEEE-754 Double Maximum
static constexpr int64_t AUDIO_BLOCK_MAX_RENDER_SIZE = 2048;
Expand All @@ -28,7 +30,7 @@ ASE_STRUCT_DECLS (ClapParamUpdate);
ASE_STRUCT_DECLS (ClipNote);
ASE_STRUCT_DECLS (DeviceInfo);
ASE_STRUCT_DECLS (DriverEntry);
ASE_STRUCT_DECLS (ParamInfo);
ASE_STRUCT_DECLS (Parameter);
ASE_STRUCT_DECLS (Resource);
ASE_STRUCT_DECLS (TelemetryField);
ASE_STRUCT_DECLS (TelemetrySegment);
Expand All @@ -54,9 +56,11 @@ ASE_CLASS_DECLS (Monitor);
ASE_CLASS_DECLS (NativeDevice);
ASE_CLASS_DECLS (NativeDeviceImpl);
ASE_CLASS_DECLS (Object);
ASE_CLASS_DECLS (Preference);
ASE_CLASS_DECLS (Project);
ASE_CLASS_DECLS (ProjectImpl);
ASE_CLASS_DECLS (Property);
ASE_CLASS_DECLS (PropertyImpl);
ASE_CLASS_DECLS (ResourceCrawler);
ASE_CLASS_DECLS (Server);
ASE_CLASS_DECLS (ServerImpl);
Expand Down
15 changes: 10 additions & 5 deletions ase/driver-alsa.cc
Original file line number Diff line number Diff line change
Expand Up @@ -369,13 +369,18 @@ class AlsaPcmDriver : public PcmDriver {
snd_pcm_close (write_handle_);
delete[] period_buffer_;
}
virtual float
pcm_frequency () const override
uint
pcm_n_channels () const override
{
return n_channels_;
}
uint
pcm_mix_freq () const override
{
return mix_freq_;
}
virtual uint
block_length () const override
uint
pcm_block_length () const override
{
return period_size_;
}
Expand Down Expand Up @@ -639,7 +644,7 @@ class AlsaPcmDriver : public PcmDriver {
*timeoutp = diff_frames * 1000 / mix_freq_;
return false;
}
virtual void
void
pcm_latency (uint *rlatency, uint *wlatency) const override
{
snd_pcm_sframes_t rdelay, wdelay;
Expand Down
15 changes: 10 additions & 5 deletions ase/driver-jack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -558,13 +558,18 @@ class JackPcmDriver : public PcmDriver {
if (jack_client_)
close();
}
virtual float
pcm_frequency () const override
uint
pcm_n_channels () const override
{
return n_channels_;
}
uint
pcm_mix_freq () const override
{
return mix_freq_;
}
virtual uint
block_length () const override
uint
pcm_block_length () const override
{
return block_length_;
}
Expand Down Expand Up @@ -785,7 +790,7 @@ class JackPcmDriver : public PcmDriver {
*timeoutp = std::max<int> (*timeoutp, 1);
return false;
}
virtual void
void
pcm_latency (uint *rlatency, uint *wlatency) const override
{
assert_return (jack_client_ != NULL);
Expand Down
25 changes: 15 additions & 10 deletions ase/driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -281,16 +281,27 @@ class NullPcmDriver : public PcmDriver {
auto pdriverp = std::make_shared<NullPcmDriver> (kvpair_key (devid), kvpair_value (devid));
return pdriverp;
}
virtual float
pcm_frequency () const override
uint
pcm_n_channels () const override
{
return n_channels_;
}
uint
pcm_mix_freq () const override
{
return mix_freq_;
}
virtual uint
block_length () const override
uint
pcm_block_length () const override
{
return block_size_;
}
void
pcm_latency (uint *rlatency, uint *wlatency) const override
{
*rlatency = mix_freq_ / 10;
*wlatency = mix_freq_ / 10;
}
virtual void
close () override
{
Expand All @@ -313,12 +324,6 @@ class NullPcmDriver : public PcmDriver {
DDEBUG ("NULL-PCM: opening with freq=%f channels=%d: %s", mix_freq_, n_channels_, ase_error_blurb (Error::NONE));
return Error::NONE;
}
virtual void
pcm_latency (uint *rlatency, uint *wlatency) const override
{
*rlatency = mix_freq_ / 10;
*wlatency = mix_freq_ / 10;
}
virtual bool
pcm_check_io (int64 *timeout_usecs) override
{
Expand Down
29 changes: 15 additions & 14 deletions ase/driver.hh
Original file line number Diff line number Diff line change
Expand Up @@ -88,27 +88,28 @@ using MidiDriverP = MidiDriver::MidiDriverP;
struct PcmDriverConfig {
uint n_channels = 0;
uint mix_freq = 0;
uint latency_ms = 0;
uint block_length = 0;
uint latency_ms = 0;
};

class PcmDriver : public Driver {
protected:
explicit PcmDriver (const String &driver, const String &devid);
virtual Ase::Error open (IODir iodir, const PcmDriverConfig &config) = 0;
explicit PcmDriver (const String &driver, const String &devid);
virtual Ase::Error open (IODir iodir, const PcmDriverConfig &config) = 0;
public:
typedef std::shared_ptr<PcmDriver> PcmDriverP;
static PcmDriverP open (const String &devid, IODir desired, IODir required, const PcmDriverConfig &config, Ase::Error *ep);
virtual bool pcm_check_io (int64 *timeoutp) = 0;
virtual void pcm_latency (uint *rlatency, uint *wlatency) const = 0;
virtual float pcm_frequency () const = 0;
virtual uint block_length () const = 0;
virtual size_t pcm_read (size_t n, float *values) = 0;
virtual void pcm_write (size_t n, const float *values) = 0;
static EntryVec list_drivers ();
static String register_driver (const String &driverid,
const std::function<PcmDriverP (const String&)> &create,
const std::function<void (EntryVec&)> &list);
static PcmDriverP open (const String &devid, IODir desired, IODir required, const PcmDriverConfig &config, Ase::Error *ep);
virtual uint pcm_n_channels () const = 0;
virtual uint pcm_mix_freq () const = 0;
virtual uint pcm_block_length () const = 0;
virtual void pcm_latency (uint *rlatency, uint *wlatency) const = 0;
virtual bool pcm_check_io (int64 *timeoutp) = 0;
virtual size_t pcm_read (size_t n, float *values) = 0;
virtual void pcm_write (size_t n, const float *values) = 0;
static EntryVec list_drivers ();
static String register_driver (const String &driverid,
const std::function<PcmDriverP (const String&)> &create,
const std::function<void (EntryVec&)> &list);
};
using PcmDriverP = PcmDriver::PcmDriverP;

Expand Down
Loading

0 comments on commit c7ece44

Please sign in to comment.