Skip to content

Commit c7ece44

Browse files
committed
Merge branch 'preferences' and live PCM driver updates
* 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 <timj@gnu.org>
2 parents 3a7c2d3 + cbdc9fc commit c7ece44

48 files changed

Lines changed: 2061 additions & 1643 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ase/api.hh

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
namespace Ase {
99

1010
// == Property hint constants ==
11-
extern const String STORAGE; // ":r:w:S:";
12-
extern const String STANDARD; // ":r:w:S:G:";
11+
constexpr const char GUIONLY[] = ":G:r:w:"; ///< GUI READABLE WRITABLE
12+
constexpr const char STORAGE[] = ":S:r:w:"; ///< STORAGE READABLE WRITABLE
13+
constexpr const char STANDARD[] = ":S:G:r:w:"; ///< STORAGE GUI READABLE WRITABLE
1314

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

158-
// Preferences
159-
struct Preferences {
160-
// Synthesis Settings
161-
String pcm_driver; ///< Driver and device to be used for PCM input and output.
162-
int32 synth_latency = 5; ///< Processing duration between input and output of a single sample, smaller values increase CPU load.
163-
int32 synth_mixing_freq = 48000; ///< Unused, synthesis mixing frequency is always 48000 Hz.
164-
int32 synth_control_freq = 1500; ///< Unused frequency setting.
165-
// MIDI
166-
String midi_driver_1; ///< Driver and device to be used for MIDI input and output.
167-
String midi_driver_2;
168-
String midi_driver_3;
169-
String midi_driver_4;
170-
bool invert_sustain = false;
171-
// Default Values
172-
String author_default; ///< Default value for 'Author' fields.
173-
String license_default; ///< Default value for 'License' fields.
174-
String sample_path; ///< Search path of directories, seperated by ";", used to find audio samples.
175-
String effect_path; ///< Search path of directories, seperated by ";", used to find effect files.
176-
String instrument_path; ///< Search path of directories, seperated by ";", used to find instrument files.
177-
String plugin_path; ///< Search path of directories, seperated by \";\", used to find plugins.
178-
///< This path is searched for in addition to the standard plugin location on this system.
179-
private:
180-
PropertyS access_properties (const EventHandler&); ///< Retrieve handles for all properties.
181-
friend class ServerImpl;
182-
};
183-
184159
/// Base type for classes with Property interfaces.
185160
class Object : public virtual Emittable {
186161
protected:
@@ -394,9 +369,9 @@ public:
394369
virtual uint64 user_note (const String &text, const String &channel = "misc", UserNote::Flags flags = UserNote::TRANSIENT, const String &rest = "") = 0;
395370
virtual bool user_reply (uint64 noteid, uint r) = 0;
396371
virtual bool broadcast_telemetry (const TelemetrySegmentS &segments,
397-
int32 interval_ms) = 0; ///< Broadcast telemetry memory segments to the current Jsonipc connection.
398-
// preferences
399-
virtual PropertyS access_prefs () = 0; ///< Retrieve property handles for Preferences fields.
372+
int32 interval_ms) = 0; ///< Broadcast telemetry memory segments to the current Jsonipc connection.
373+
virtual StringS list_preferences () = 0; ///< Retrieve a list of all preference identifiers.
374+
virtual PropertyP access_preference (const String &ident) = 0; ///< Retrieve property handle for a Preference identifier.
400375
// projects
401376
virtual ProjectP last_project () = 0; ///< Retrieve the last created project.
402377
virtual ProjectP create_project (String projectname) = 0; ///< Create a new project (name is modified to be unique if necessary.

ase/clapdevice.cc

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,21 @@ struct ClapPropertyImpl : public Property, public virtual EmittableImpl {
2727
String ident_, label_, module_;
2828
double min_value = NAN, max_value = NAN, default_value = NAN;
2929
public:
30-
String identifier () override { return ident_; }
31-
String label () override { return label_; }
32-
String nick () override { return property_guess_nick (label_); }
33-
String unit () override { return ""; }
34-
String hints () override { return ClapParamInfo::hints_from_param_info_flags (flags); }
35-
String group () override { return module_; }
36-
String blurb () override { return ""; }
37-
String description () override { return ""; }
38-
double get_min () override { return min_value; }
39-
double get_max () override { return max_value; }
40-
double get_step () override { return is_stepped() ? 1 : 0; }
41-
bool is_numeric () override { return true; }
42-
bool is_stepped () { return strstr (hints().c_str(), ":stepped:"); }
43-
void reset () override { set_value (default_value); }
44-
ClapPropertyImpl (ClapDeviceImplP device, const ClapParamInfo info) :
30+
String ident () override { return ident_; }
31+
String label () override { return label_; }
32+
String nick () override { return parameter_guess_nick (label_); }
33+
String unit () override { return ""; }
34+
String hints () override { return ClapParamInfo::hints_from_param_info_flags (flags); }
35+
String group () override { return module_; }
36+
String blurb () override { return ""; }
37+
String descr () override { return ""; }
38+
double get_min () override { return min_value; }
39+
double get_max () override { return max_value; }
40+
double get_step () override { return is_stepped() ? 1 : 0; }
41+
bool is_numeric () override { return true; }
42+
bool is_stepped () { return strstr (hints().c_str(), ":stepped:"); }
43+
void reset () override { set_value (default_value); }
44+
ClapPropertyImpl (ClapDeviceImplP device, const ClapParamInfo info) :
4545
device_ (device)
4646
{
4747
param_id = info.param_id;

ase/cxxaux.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
22
#include "cxxaux.hh"
3-
#include "main.hh" // main_config
3+
#include "utils.hh" // ase_fatal_warnings
44
#include "backtrace.hh"
55
#include <cxxabi.h> // abi::__cxa_demangle
66
#include <signal.h>
@@ -45,7 +45,7 @@ assertion_failed (const std::string &msg, const char *file, int line, const char
4545
ASE_PRINT_BACKTRACE (__FILE__, __LINE__, __func__);
4646
else if (debug_key_enabled ("break"))
4747
breakpoint();
48-
if (main_config.fatal_warnings)
48+
if (ase_fatal_warnings)
4949
raise (SIGQUIT);
5050
}
5151

ase/cxxaux.hh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ using VoidF = std::function<void()>;
9090
/// Like ASE_ASSERT_WARN(), enabled if expensive `expr` are allowed.
9191
#define ASE_ASSERT_PARANOID(expr) do { if (ASE_ISLIKELY (expr)) break; ::Ase::assertion_failed (#expr); } while (0)
9292

93+
/// Return from the current function if `expr` evaluates to false and issue an assertion warning.
94+
#define ASE_ASSERT_ALWAYS(expr, ...) do { if (ASE_ISLIKELY (expr)) break; ::Ase::assertion_failed (#expr); __builtin_trap(); } while (0)
95+
9396
/// Delete copy ctor and assignment operator.
9497
#define ASE_CLASS_NON_COPYABLE(ClassName) \
9598
/*copy-ctor*/ ClassName (const ClassName&) = delete; \

ase/defs.hh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ static constexpr uint32_t U32MAX = +4294967295u; // 2^32-1
1414
static constexpr int32_t I31MAX = +2147483647; // 2^31-1
1515
static constexpr int32_t I31MIN = -2147483648; // -2^31
1616
static constexpr float M23MAX = 16777216; // 2^(1+23); IEEE-754 Float Mantissa maximum
17+
static constexpr float F32EPS = 5.9604644775390625e-08; // 2^-24, round-off error at 1.0
18+
static constexpr float F32MAX = 3.40282347e+38; // 7f7fffff, 2^128 * (1 - F32EPS)
1719
static constexpr double M52MAX = 9007199254740992; // 2^(1+52); IEEE-754 Double Mantissa maximum
1820
static constexpr double D64MAX = 1.7976931348623157e+308; // 0x7fefffff ffffffff, IEEE-754 Double Maximum
1921
static constexpr int64_t AUDIO_BLOCK_MAX_RENDER_SIZE = 2048;
@@ -28,7 +30,7 @@ ASE_STRUCT_DECLS (ClapParamUpdate);
2830
ASE_STRUCT_DECLS (ClipNote);
2931
ASE_STRUCT_DECLS (DeviceInfo);
3032
ASE_STRUCT_DECLS (DriverEntry);
31-
ASE_STRUCT_DECLS (ParamInfo);
33+
ASE_STRUCT_DECLS (Parameter);
3234
ASE_STRUCT_DECLS (Resource);
3335
ASE_STRUCT_DECLS (TelemetryField);
3436
ASE_STRUCT_DECLS (TelemetrySegment);
@@ -54,9 +56,11 @@ ASE_CLASS_DECLS (Monitor);
5456
ASE_CLASS_DECLS (NativeDevice);
5557
ASE_CLASS_DECLS (NativeDeviceImpl);
5658
ASE_CLASS_DECLS (Object);
59+
ASE_CLASS_DECLS (Preference);
5760
ASE_CLASS_DECLS (Project);
5861
ASE_CLASS_DECLS (ProjectImpl);
5962
ASE_CLASS_DECLS (Property);
63+
ASE_CLASS_DECLS (PropertyImpl);
6064
ASE_CLASS_DECLS (ResourceCrawler);
6165
ASE_CLASS_DECLS (Server);
6266
ASE_CLASS_DECLS (ServerImpl);

ase/driver-alsa.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,13 +369,18 @@ class AlsaPcmDriver : public PcmDriver {
369369
snd_pcm_close (write_handle_);
370370
delete[] period_buffer_;
371371
}
372-
virtual float
373-
pcm_frequency () const override
372+
uint
373+
pcm_n_channels () const override
374+
{
375+
return n_channels_;
376+
}
377+
uint
378+
pcm_mix_freq () const override
374379
{
375380
return mix_freq_;
376381
}
377-
virtual uint
378-
block_length () const override
382+
uint
383+
pcm_block_length () const override
379384
{
380385
return period_size_;
381386
}
@@ -639,7 +644,7 @@ class AlsaPcmDriver : public PcmDriver {
639644
*timeoutp = diff_frames * 1000 / mix_freq_;
640645
return false;
641646
}
642-
virtual void
647+
void
643648
pcm_latency (uint *rlatency, uint *wlatency) const override
644649
{
645650
snd_pcm_sframes_t rdelay, wdelay;

ase/driver-jack.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -558,13 +558,18 @@ class JackPcmDriver : public PcmDriver {
558558
if (jack_client_)
559559
close();
560560
}
561-
virtual float
562-
pcm_frequency () const override
561+
uint
562+
pcm_n_channels () const override
563+
{
564+
return n_channels_;
565+
}
566+
uint
567+
pcm_mix_freq () const override
563568
{
564569
return mix_freq_;
565570
}
566-
virtual uint
567-
block_length () const override
571+
uint
572+
pcm_block_length () const override
568573
{
569574
return block_length_;
570575
}
@@ -785,7 +790,7 @@ class JackPcmDriver : public PcmDriver {
785790
*timeoutp = std::max<int> (*timeoutp, 1);
786791
return false;
787792
}
788-
virtual void
793+
void
789794
pcm_latency (uint *rlatency, uint *wlatency) const override
790795
{
791796
assert_return (jack_client_ != NULL);

ase/driver.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -281,16 +281,27 @@ class NullPcmDriver : public PcmDriver {
281281
auto pdriverp = std::make_shared<NullPcmDriver> (kvpair_key (devid), kvpair_value (devid));
282282
return pdriverp;
283283
}
284-
virtual float
285-
pcm_frequency () const override
284+
uint
285+
pcm_n_channels () const override
286+
{
287+
return n_channels_;
288+
}
289+
uint
290+
pcm_mix_freq () const override
286291
{
287292
return mix_freq_;
288293
}
289-
virtual uint
290-
block_length () const override
294+
uint
295+
pcm_block_length () const override
291296
{
292297
return block_size_;
293298
}
299+
void
300+
pcm_latency (uint *rlatency, uint *wlatency) const override
301+
{
302+
*rlatency = mix_freq_ / 10;
303+
*wlatency = mix_freq_ / 10;
304+
}
294305
virtual void
295306
close () override
296307
{
@@ -313,12 +324,6 @@ class NullPcmDriver : public PcmDriver {
313324
DDEBUG ("NULL-PCM: opening with freq=%f channels=%d: %s", mix_freq_, n_channels_, ase_error_blurb (Error::NONE));
314325
return Error::NONE;
315326
}
316-
virtual void
317-
pcm_latency (uint *rlatency, uint *wlatency) const override
318-
{
319-
*rlatency = mix_freq_ / 10;
320-
*wlatency = mix_freq_ / 10;
321-
}
322327
virtual bool
323328
pcm_check_io (int64 *timeout_usecs) override
324329
{

ase/driver.hh

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,28 @@ using MidiDriverP = MidiDriver::MidiDriverP;
8888
struct PcmDriverConfig {
8989
uint n_channels = 0;
9090
uint mix_freq = 0;
91-
uint latency_ms = 0;
9291
uint block_length = 0;
92+
uint latency_ms = 0;
9393
};
9494

9595
class PcmDriver : public Driver {
9696
protected:
97-
explicit PcmDriver (const String &driver, const String &devid);
98-
virtual Ase::Error open (IODir iodir, const PcmDriverConfig &config) = 0;
97+
explicit PcmDriver (const String &driver, const String &devid);
98+
virtual Ase::Error open (IODir iodir, const PcmDriverConfig &config) = 0;
9999
public:
100100
typedef std::shared_ptr<PcmDriver> PcmDriverP;
101-
static PcmDriverP open (const String &devid, IODir desired, IODir required, const PcmDriverConfig &config, Ase::Error *ep);
102-
virtual bool pcm_check_io (int64 *timeoutp) = 0;
103-
virtual void pcm_latency (uint *rlatency, uint *wlatency) const = 0;
104-
virtual float pcm_frequency () const = 0;
105-
virtual uint block_length () const = 0;
106-
virtual size_t pcm_read (size_t n, float *values) = 0;
107-
virtual void pcm_write (size_t n, const float *values) = 0;
108-
static EntryVec list_drivers ();
109-
static String register_driver (const String &driverid,
110-
const std::function<PcmDriverP (const String&)> &create,
111-
const std::function<void (EntryVec&)> &list);
101+
static PcmDriverP open (const String &devid, IODir desired, IODir required, const PcmDriverConfig &config, Ase::Error *ep);
102+
virtual uint pcm_n_channels () const = 0;
103+
virtual uint pcm_mix_freq () const = 0;
104+
virtual uint pcm_block_length () const = 0;
105+
virtual void pcm_latency (uint *rlatency, uint *wlatency) const = 0;
106+
virtual bool pcm_check_io (int64 *timeoutp) = 0;
107+
virtual size_t pcm_read (size_t n, float *values) = 0;
108+
virtual void pcm_write (size_t n, const float *values) = 0;
109+
static EntryVec list_drivers ();
110+
static String register_driver (const String &driverid,
111+
const std::function<PcmDriverP (const String&)> &create,
112+
const std::function<void (EntryVec&)> &list);
112113
};
113114
using PcmDriverP = PcmDriver::PcmDriverP;
114115

0 commit comments

Comments
 (0)