22static constexpr size_t telemetry_size = 4 * 1024 * 1024;
24ServerImpl *SERVER =
nullptr;
26ServerImpl::ServerImpl () :
27 telemetry_arena (telemetry_size)
30 Block telemetry_header = telemetry_arena.allocate (64);
32 const uint8_t header_sentinel[64] = {
33 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
34 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
35 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b,
36 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
38 assert_return (telemetry_header.block_length == sizeof (header_sentinel));
39 memcpy (telemetry_header.block_start, header_sentinel, telemetry_header.block_length);
44ServerImpl::~ServerImpl ()
46 fatal_error (
"ServerImpl references must persist");
52ServerImpl::get_version ()
58ServerImpl::get_build_id ()
64ServerImpl::get_opus_version ()
66 return wave_writer_opus_version();
70ServerImpl::get_flac_version ()
72 return wave_writer_flac_version();
76ServerImpl::get_clap_version()
78 return ClapDeviceImpl::clap_version();
82ServerImpl::get_sndfile_version ()
84 return libsndfile_version();
88ServerImpl::shutdown ()
95ServerImpl::last_project ()
97 return Project::last_project();
101ServerImpl::create_project (
String projectname)
103 return ProjectImpl::create (projectname);
107ServerImpl::list_preferences ()
109 const CStringS list = Preference::list();
114ServerImpl::access_preference (
const String &ident)
116 return Preference::find (ident);
120ServerImpl::instancep ()
129 const String ckey = canonify_key (key);
130 if (ckey.
size() && ckey[0] !=
'_')
132 const String filename = Path::join (Path::xdg_dir (
"CONFIG"),
"anklang", ckey);
133 emit_event (
"data", key);
134 return Path::stringwrite (filename, value.
as_string());
137 return GadgetImpl::set_data (ckey, value);
141ServerImpl::get_data (
const String &key)
const
143 const String ckey = canonify_key (key);
144 if (ckey.
size() && ckey[0] !=
'_')
146 const String filename = Path::join (Path::xdg_dir (
"CONFIG"),
"anklang", ckey);
147 return Path::stringread (filename);
150 return GadgetImpl::get_data (ckey);
157 return ServerImpl::instancep();
170 return FileCrawler::make_shared (cwd,
true,
false);
176 if (App.web_socket_server) {
177 String dir = App.web_socket_server->map_url (url);
179 return FileCrawler::make_shared (dir,
false,
false);
185Server::engine_stats ()
187 const String s = App.engine->engine_stats (0);
188 printerr (
"Server::engine_stats:\n%s\n", s);
193Server::exit_program (
int status)
195 main_loop->quit (status);
201 label (label_), blurb (blurb_), notice (notice_), warning (warning_)
208 icon (icon_), label (label_), blurb (blurb_), notice (notice_), warning (warning_)
213Choice::Choice (IconString icon_,
String label_,
String blurb_) :
214 Choice (
"", icon_, label_, blurb_)
220 choices.push_back (std::move (newchoice));
232 case Error::NONE:
return _(
"OK");
234 case Error::INTERNAL:
return _(
"Internal error (please report)");
236 case Error::FILE_EOF:
return _(
"End of file");
237 case Error::FILE_OPEN_FAILED:
return _(
"Open failed");
238 case Error::FILE_SEEK_FAILED:
return _(
"Seek failed");
239 case Error::FILE_READ_FAILED:
return _(
"Read failed");
240 case Error::FILE_WRITE_FAILED:
return _(
"Write failed");
242 case Error::PARSE_ERROR:
return _(
"Parsing error");
243 case Error::NO_HEADER:
return _(
"Failed to detect header");
244 case Error::NO_SEEK_INFO:
return _(
"Failed to retrieve seek information");
245 case Error::NO_DATA_AVAILABLE:
return _(
"No data available");
246 case Error::DATA_CORRUPT:
return _(
"Data corrupt");
247 case Error::WRONG_N_CHANNELS:
return _(
"Wrong number of channels");
248 case Error::FORMAT_INVALID:
return _(
"Invalid format");
249 case Error::FORMAT_UNKNOWN:
return _(
"Unknown format");
250 case Error::DATA_UNMATCHED:
return _(
"Requested data values unmatched");
251 case Error::CODEC_FAILURE:
return _(
"Codec failure");
252 case Error::BROKEN_ARCHIVE:
return _(
"Broken archive");
253 case Error::BAD_PROJECT:
return _(
"Not a valid project");
254 case Error::NO_PROJECT_DIR:
return _(
"Missing project directory");
256 case Error::DEVICE_NOT_AVAILABLE:
return _(
"No device (driver) available");
257 case Error::DEVICE_ASYNC:
return _(
"Device not async capable");
258 case Error::DEVICE_BUSY:
return _(
"Device busy");
259 case Error::DEVICE_FORMAT:
return _(
"Failed to configure device format");
260 case Error::DEVICE_BUFFER:
return _(
"Failed to configure device buffer");
261 case Error::DEVICE_LATENCY:
return _(
"Failed to configure device latency");
262 case Error::DEVICE_CHANNELS:
return _(
"Failed to configure number of device channels");
263 case Error::DEVICE_FREQUENCY:
return _(
"Failed to configure device frequency");
264 case Error::DEVICES_MISMATCH:
return _(
"Device configurations mismatch");
266 case Error::WAVE_NOT_FOUND:
return _(
"No such wave");
267 case Error::UNIMPLEMENTED:
return _(
"Functionality not implemented");
268 case Error::INVALID_PROPERTY:
return _(
"Invalid object property");
269 case Error::INVALID_MIDI_CONTROL:
return _(
"Invalid MIDI control type");
270 case Error::OPERATION_BUSY:
return _(
"Operation already in prgress");
278ase_error_from_errno (
int sys_errno,
Error fallback)
280 if (sys_errno <
int (Error::INTERNAL))
281 return Error (sys_errno);
287ServerImpl::error_blurb (
Error error)
const
296 switch (musicaltuning)
299 case MusicalTuning::OD_12_TET:
300 return {
_(
"12 Tone Equal Temperament"),
301 _(
"The most common tuning system for modern Western music, "
302 "is the twelve-tone equal temperament, abbreviated as 12-TET, "
303 "which divides the octave into 12 equal parts.") };
304 case MusicalTuning::OD_7_TET:
305 return {
_(
"7 Tone Equal Temperament"),
306 _(
"A fairly common tuning system is the seven-tone equal temperament tuning system, "
307 "abbreviated as 7-TET. It divides the octave into 7 equal parts using 171 cent steps.") };
308 case MusicalTuning::OD_5_TET:
309 return {
_(
"5 Tone Equal Temperament"),
310 _(
"A fairly common tuning system is the five-tone equal temperament tuning system, "
311 "abbreviated as 5-TET. It divides the octave into 5 equal parts using 240 cent steps.") };
313 case MusicalTuning::DIATONIC_SCALE:
314 return {
_(
"Diatonic Scale"),
315 _(
"In music theory, a diatonic scale (also: heptatonia prima) is a seven-note "
316 "musical scale comprising five whole-tone and two half-tone steps. "
317 "The half tones are maximally separated, so between two half-tone steps "
318 "there are either two or three whole tones, repeating per octave.") };
319 case MusicalTuning::INDIAN_SCALE:
320 return {
_(
"Indian Scale"),
321 _(
"Diatonic scale used in Indian music with wolf interval at Dha, close to 3/2") };
322 case MusicalTuning::PYTHAGOREAN_TUNING:
323 return {
_(
"Pythagorean Tuning"),
324 _(
"Pythagorean tuning is the oldest way of tuning the 12-note chromatic scale, "
325 "in which the frequency relationships of all intervals are based on the ratio 3:2. "
326 "Its discovery is generally credited to Pythagoras.") };
327 case MusicalTuning::PENTATONIC_5_LIMIT:
328 return {
_(
"Pentatonic 5-limit"),
329 _(
"Pentatonic scales are used in modern jazz and pop/rock contexts "
330 "because they work exceedingly well over several chords diatonic "
331 "to the same key, often better than the parent scale.") };
332 case MusicalTuning::PENTATONIC_BLUES:
333 return {
_(
"Pentatonic Blues"),
334 _(
"The blues scale is the minor pentatonic with an additional augmented fourth, "
335 "which is referred to as the \"blues note\".") };
336 case MusicalTuning::PENTATONIC_GOGO:
337 return {
_(
"Pentatonic Gogo"),
338 _(
"The Pentatonic Gogo scale is an anhemitonic pentatonic scale used to tune the "
339 "instruments of the Gogo people of Tanzania.") };
341 case MusicalTuning::QUARTER_COMMA_MEANTONE:
342 return {
_(
"Quarter-Comma Meantone"),
343 _(
"Quarter-comma meantone was the most common meantone temperament in the "
344 "sixteenth and seventeenth centuries and sometimes used later.") };
345 case MusicalTuning::SILBERMANN_SORGE:
346 return {
_(
"Silbermann-Sorge Temperament"),
347 _(
"The Silbermann-Sorge temperament is a meantone temperament used for "
348 "Baroque era organs by Gottfried Silbermann.") };
350 case MusicalTuning::WERCKMEISTER_3:
351 return {
_(
"Werckmeister III"),
352 _(
"This tuning uses mostly pure (perfect) fifths, as in Pythagorean tuning, but each "
353 "of the fifths C-G, G-D, D-A and B-F# is made smaller, i.e. tempered by 1/4 comma. "
354 "Werckmeister designated this tuning as particularly suited for playing chromatic music.") };
355 case MusicalTuning::WERCKMEISTER_4:
356 return {
_(
"Werckmeister IV"),
357 _(
"In this tuning the fifths C-G, D-A, E-B, F#-C#, and Bb-F are tempered narrow by 1/3 comma, "
358 "and the fifths G#-D# and Eb-Bb are widened by 1/3 comma. The other fifths are pure. "
359 "Most of its intervals are close to sixth-comma meantone. "
360 "Werckmeister designed this tuning for playing mainly diatonic music.") };
361 case MusicalTuning::WERCKMEISTER_5:
362 return {
_(
"Werckmeister V"),
363 _(
"In this tuning the fifths D-A, A-E, F#-C#, C#-G#, and F-C are narrowed by 1/4 comma, "
364 "and the fifth G#-D# is widened by 1/4 comma. The other fifths are pure. "
365 "This temperament is closer to equal temperament than Werckmeister III or IV.") };
366 case MusicalTuning::WERCKMEISTER_6:
367 return {
_(
"Werckmeister VI"),
368 _(
"This tuning is also known as Septenarius tuning is based on a division of the monochord "
369 "length into 196 = 7 * 7 * 4 parts. "
370 "The resulting scale has rational frequency relationships, but in practice involves pure "
371 "and impure sounding fifths. "
372 "Werckmeister described the Septenarius as a \"temperament which has nothing at all to do "
373 "with the divisions of the comma, nevertheless in practice so correct that one can be really "
374 "satisfied with it\".") };
375 case MusicalTuning::KIRNBERGER_3:
376 return {
_(
"Kirnberger III"),
377 _(
"Kirnberger's method of compensating for and closing the circle of fifths is to split the \"wolf\" "
378 "interval known to those who have used meantone temperaments between four fifths instead, "
379 "allowing for four 1/4-comma wolves to take their place. "
380 "1/4-comma wolves are used extensively in meantone and are much easier to tune and to listen to. "
381 "Therefore, only one third remains pure (between C and E).") };
382 case MusicalTuning::YOUNG:
383 return {
_(
"Young Temperament"),
384 _(
"Thomas Young devised a form of musical tuning to make the harmony most perfect in those keys which "
385 "are the most frequently used (give better major thirds in those keys), but to not have any unplayable keys. "
386 "This is attempted by tuning upwards from C a sequence of six pure fourths, "
387 "as well as six equally imperfect fifths.") };
392static bool musical_tuning_info__ = EnumInfo::impl (musical_tuning_info);
395ServerImpl::musical_tuning_blurb (
MusicalTuning musicaltuning)
const
397 return EnumInfo::value_info (musicaltuning).blurb;
401ServerImpl::musical_tuning_label (
MusicalTuning musicaltuning)
const
403 return EnumInfo::value_info (musicaltuning).label;
409ServerImpl::user_note (
const String &text,
const String &channel, UserNote::Flags flags,
const String &rest)
411 UserNote unote { user_note_id++, flags, channel.empty() ?
"misc" : channel, text, rest };
414 this->emit_event (
"usernote",
"", vrec);
417 if (!unote.rest.empty())
418 s +=
" (" + unote.rest +
")";
430ServerImpl::telemem_allocate (
uint32 length)
const
432 return telemetry_arena.
allocate (length);
436ServerImpl::telemem_release (Block telememblock)
const
438 telemetry_arena.
release (telememblock);
442ServerImpl::telemem_start ()
const
448validate_telemetry_segments (
const TelemetrySegmentS &segments,
size_t *payloadlength)
451 const TelemetrySegment *last =
nullptr;
452 for (
const auto &seg : segments)
454 if (last && seg.offset < last->offset + last->length)
456 if (seg.offset < 0 || (seg.offset & 3) || seg.length <= 0 || (seg.length & 3) ||
457 size_t (seg.offset + seg.length) > telemetry_size)
459 *payloadlength += seg.length;
465ASE_CLASS_DECLS (TelemetryPlan);
468 int32 interval_ms_ = -1;
469 LoopID timerid_ = LoopID::INVALID;
471 TelemetrySegmentS segments_;
472 const char *telemem_ =
nullptr;
474 void send_telemetry();
475 void setup (
const char *start,
size_t payloadlength,
const TelemetrySegmentS &plan,
int32 interval_ms);
483 size_t payloadlength = 0;
484 if (!validate_telemetry_segments (segments, &payloadlength))
486 warning (
"%s: invalid segment list",
"Ase::ServerImpl::broadcast_telemetry");
492 warning (
"%s: cannot broadcast telemetry without jsonapi connection",
"Ase::ServerImpl::broadcast_telemetry");
500 tplan->send_blob_ = jsonapi_connection_sender();
502 tplan->setup ((
const char*) telemetry_arena.
location(), payloadlength, segments, interval_ms);
507TelemetryPlan::setup (
const char *start,
size_t payloadlength,
const TelemetrySegmentS &segments,
int32 interval_ms)
509 if (timerid_ == LoopID::INVALID || interval_ms_ != interval_ms)
511 if (timerid_ != LoopID::INVALID)
512 main_loop->cancel (timerid_);
513 auto send_telemetry = [
this] () { this->send_telemetry();
return true; };
514 interval_ms_ = interval_ms;
515 timerid_ = interval_ms <= 0 || segments.empty() ? LoopID::INVALID : main_loop->add (send_telemetry,
std::chrono::milliseconds (interval_ms));
517 if (timerid_ != LoopID::INVALID)
520 segments_ = segments;
521 payload_.
resize (payloadlength);
532TelemetryPlan::send_telemetry ()
534 char *
data = &payload_[0];
536 for (
const auto &seg : segments_)
538 memcpy (data + datapos, telemem_ + seg.offset, seg.length);
539 datapos += seg.length;
541 send_blob_ (payload_);
544TelemetryPlan::~TelemetryPlan()
546 if (timerid_ != LoopID::INVALID)
548 main_loop->cancel (timerid_);
549 timerid_ = LoopID::INVALID;
DataListContainer - typesafe storage and retrieval of arbitrary members.
T get_custom_data(CustomDataKey< T > *key) const
Retrieve contents of the custom keyed data member, returns DataKey::fallback if nothing was set.
void set_custom_data(CustomDataKey< T > *key, T data)
Assign data to the custom keyed data member, deletes any previously set data.
CustomDataKey objects are used to identify and manage custom data members of CustomDataContainer obje...
bool broadcast_telemetry(const TelemetrySegmentS &plan, int32 interval_ms) override
Broadcast telemetry memory segments to the current Jsonipc connection.
Central singleton, serves as API entry point.
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
#define _(...)
Retrieve the translation of a C or C++ string.
The Anklang C++ API namespace.
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
String string_to_identifier(const String &input)
Force lower case, alphanumerics + underscore and non-digit start.
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
int32_t int32
A 32-bit signed integer.
bool json_parse(const String &jsonstring, T &target)
Parse a well formed JSON string and assign contents to target.
Error
Enum representing Error states.
const char * ase_error_blurb(Error error)
Describe Error condition.
String string_replace(const String &input, const String &marker, const String &replacement, size_t maxn)
Replace substring marker in input with replacement, at most maxn times.
ChoiceS & operator+=(ChoiceS &choices, Choice &&newchoice)
Convenience ChoiceS construction helper.
String program_alias()
Retrieve the program name as used for logging or debug messages.
const char * ase_version()
Provide a string containing the package version.
std::string String
Convenience alias for std::string.
uint32_t uint32
A 32-bit unsigned integer.
uint32_t uint
Provide 'uint' as convenience type.
String json_stringify(const T &source, Writ::Flags flags=Writ::Flags(0))
Create JSON string from source.
MusicalTuning
Musical tunings, see: http://en.wikipedia.org/wiki/Musical_tuning.
const char * ase_build_id()
Provide a string containing the ASE library build id.
unsigned long long uint64
Representation of one possible choice for selection properties.
uint64 location() const
Address of memory area.
Block allocate(uint32 length) const
Create a memory block from cache-line aligned memory area, MT-Unsafe.
void release(Block allocatedblock) const
Realease a previously allocated block, MT-Unsafe.
Value type used to interface with various property types.
String as_string() const
Convert Value to a string, not very useful for RECORD or ARRAY.