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 ()
91 main_loop->exec_timer ([] () { main_loop->quit (0); }, 5, -1, EventLoop::PRIORITY_NORMAL);
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;
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_ == 0 || interval_ms_ != interval_ms)
512 main_loop->remove (timerid_);
513 auto send_telemetry = [
this] () { this->send_telemetry();
return true; };
514 interval_ms_ = interval_ms;
515 timerid_ = interval_ms <= 0 || segments.empty() ? 0 : main_loop->exec_timer (send_telemetry, interval_ms, interval_ms);
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()
548 main_loop->remove (timerid_);
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.
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.