21static constexpr size_t telemetry_size = 4 * 1024 * 1024;
23ServerImpl *SERVER =
nullptr;
25ServerImpl::ServerImpl () :
26 telemetry_arena (telemetry_size)
29 Block telemetry_header = telemetry_arena.allocate (64);
31 const uint8_t header_sentinel[64] = {
32 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
33 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
34 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b,
35 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
37 assert_return (telemetry_header.block_length == sizeof (header_sentinel));
38 memcpy (telemetry_header.block_start, header_sentinel, telemetry_header.block_length);
43ServerImpl::~ServerImpl ()
45 fatal_error (
"ServerImpl references must persist");
51ServerImpl::get_version ()
57ServerImpl::get_build_id ()
63ServerImpl::get_opus_version ()
65 return wave_writer_opus_version();
69ServerImpl::get_flac_version ()
71 return wave_writer_flac_version();
75ServerImpl::get_sndfile_version ()
77 return libsndfile_version();
81ServerImpl::shutdown ()
88ServerImpl::last_project ()
90 return Project::last_project();
94ServerImpl::create_project (
String projectname)
96 return ProjectImpl::create (projectname);
100ServerImpl::list_preferences ()
102 const CStringS list = Preference::list();
107ServerImpl::access_preference (
const String &ident)
109 return Preference::find (ident);
113ServerImpl::instancep ()
122 const String ckey = canonify_key (key);
123 if (ckey.
size() && ckey[0] !=
'_')
125 const String filename = Path::join (Path::xdg_dir (
"CONFIG"),
"anklang", ckey);
126 emit_event (
"data", key);
127 return Path::stringwrite (filename, value.
as_string());
130 return GadgetImpl::set_data (ckey, value);
134ServerImpl::get_data (
const String &key)
const
136 const String ckey = canonify_key (key);
137 if (ckey.
size() && ckey[0] !=
'_')
139 const String filename = Path::join (Path::xdg_dir (
"CONFIG"),
"anklang", ckey);
140 return Path::stringread (filename);
143 return GadgetImpl::get_data (ckey);
150 return ServerImpl::instancep();
163 return FileCrawler::make_shared (cwd,
true,
false);
169 if (App.web_socket_server) {
170 String dir = App.web_socket_server->map_url (url);
172 return FileCrawler::make_shared (dir,
false,
false);
178Server::engine_stats ()
180 const String s =
"Unused";
181 printerr (
"Server::engine_stats:\n%s\n", s);
186Server::exit_program (
int status)
188 main_loop->quit (status);
194 label (label_), blurb (blurb_), notice (notice_), warning (warning_)
201 icon (icon_), label (label_), blurb (blurb_), notice (notice_), warning (warning_)
206Choice::Choice (IconString icon_,
String label_,
String blurb_) :
207 Choice (
"", icon_, label_, blurb_)
213 choices.push_back (std::move (newchoice));
225 case Error::NONE:
return _(
"OK");
227 case Error::INTERNAL:
return _(
"Internal error (please report)");
229 case Error::FILE_EOF:
return _(
"End of file");
230 case Error::FILE_OPEN_FAILED:
return _(
"Open failed");
231 case Error::FILE_SEEK_FAILED:
return _(
"Seek failed");
232 case Error::FILE_READ_FAILED:
return _(
"Read failed");
233 case Error::FILE_WRITE_FAILED:
return _(
"Write failed");
235 case Error::PARSE_ERROR:
return _(
"Parsing error");
236 case Error::NO_HEADER:
return _(
"Failed to detect header");
237 case Error::NO_SEEK_INFO:
return _(
"Failed to retrieve seek information");
238 case Error::NO_DATA_AVAILABLE:
return _(
"No data available");
239 case Error::DATA_CORRUPT:
return _(
"Data corrupt");
240 case Error::WRONG_N_CHANNELS:
return _(
"Wrong number of channels");
241 case Error::FORMAT_INVALID:
return _(
"Invalid format");
242 case Error::FORMAT_UNKNOWN:
return _(
"Unknown format");
243 case Error::DATA_UNMATCHED:
return _(
"Requested data values unmatched");
244 case Error::CODEC_FAILURE:
return _(
"Codec failure");
245 case Error::BROKEN_ARCHIVE:
return _(
"Broken archive");
246 case Error::BAD_PROJECT:
return _(
"Not a valid project");
247 case Error::NO_PROJECT_DIR:
return _(
"Missing project directory");
249 case Error::DEVICE_NOT_AVAILABLE:
return _(
"No device (driver) available");
250 case Error::DEVICE_ASYNC:
return _(
"Device not async capable");
251 case Error::DEVICE_BUSY:
return _(
"Device busy");
252 case Error::DEVICE_FORMAT:
return _(
"Failed to configure device format");
253 case Error::DEVICE_BUFFER:
return _(
"Failed to configure device buffer");
254 case Error::DEVICE_LATENCY:
return _(
"Failed to configure device latency");
255 case Error::DEVICE_CHANNELS:
return _(
"Failed to configure number of device channels");
256 case Error::DEVICE_FREQUENCY:
return _(
"Failed to configure device frequency");
257 case Error::DEVICES_MISMATCH:
return _(
"Device configurations mismatch");
259 case Error::WAVE_NOT_FOUND:
return _(
"No such wave");
260 case Error::UNIMPLEMENTED:
return _(
"Functionality not implemented");
261 case Error::INVALID_PROPERTY:
return _(
"Invalid object property");
262 case Error::INVALID_MIDI_CONTROL:
return _(
"Invalid MIDI control type");
263 case Error::OPERATION_BUSY:
return _(
"Operation already in prgress");
271ase_error_from_errno (
int sys_errno,
Error fallback)
273 if (sys_errno <
int (Error::INTERNAL))
274 return Error (sys_errno);
280ServerImpl::error_blurb (
Error error)
const
289 switch (musicaltuning)
292 case MusicalTuning::OD_12_TET:
293 return {
_(
"12 Tone Equal Temperament"),
294 _(
"The most common tuning system for modern Western music, "
295 "is the twelve-tone equal temperament, abbreviated as 12-TET, "
296 "which divides the octave into 12 equal parts.") };
297 case MusicalTuning::OD_7_TET:
298 return {
_(
"7 Tone Equal Temperament"),
299 _(
"A fairly common tuning system is the seven-tone equal temperament tuning system, "
300 "abbreviated as 7-TET. It divides the octave into 7 equal parts using 171 cent steps.") };
301 case MusicalTuning::OD_5_TET:
302 return {
_(
"5 Tone Equal Temperament"),
303 _(
"A fairly common tuning system is the five-tone equal temperament tuning system, "
304 "abbreviated as 5-TET. It divides the octave into 5 equal parts using 240 cent steps.") };
306 case MusicalTuning::DIATONIC_SCALE:
307 return {
_(
"Diatonic Scale"),
308 _(
"In music theory, a diatonic scale (also: heptatonia prima) is a seven-note "
309 "musical scale comprising five whole-tone and two half-tone steps. "
310 "The half tones are maximally separated, so between two half-tone steps "
311 "there are either two or three whole tones, repeating per octave.") };
312 case MusicalTuning::INDIAN_SCALE:
313 return {
_(
"Indian Scale"),
314 _(
"Diatonic scale used in Indian music with wolf interval at Dha, close to 3/2") };
315 case MusicalTuning::PYTHAGOREAN_TUNING:
316 return {
_(
"Pythagorean Tuning"),
317 _(
"Pythagorean tuning is the oldest way of tuning the 12-note chromatic scale, "
318 "in which the frequency relationships of all intervals are based on the ratio 3:2. "
319 "Its discovery is generally credited to Pythagoras.") };
320 case MusicalTuning::PENTATONIC_5_LIMIT:
321 return {
_(
"Pentatonic 5-limit"),
322 _(
"Pentatonic scales are used in modern jazz and pop/rock contexts "
323 "because they work exceedingly well over several chords diatonic "
324 "to the same key, often better than the parent scale.") };
325 case MusicalTuning::PENTATONIC_BLUES:
326 return {
_(
"Pentatonic Blues"),
327 _(
"The blues scale is the minor pentatonic with an additional augmented fourth, "
328 "which is referred to as the \"blues note\".") };
329 case MusicalTuning::PENTATONIC_GOGO:
330 return {
_(
"Pentatonic Gogo"),
331 _(
"The Pentatonic Gogo scale is an anhemitonic pentatonic scale used to tune the "
332 "instruments of the Gogo people of Tanzania.") };
334 case MusicalTuning::QUARTER_COMMA_MEANTONE:
335 return {
_(
"Quarter-Comma Meantone"),
336 _(
"Quarter-comma meantone was the most common meantone temperament in the "
337 "sixteenth and seventeenth centuries and sometimes used later.") };
338 case MusicalTuning::SILBERMANN_SORGE:
339 return {
_(
"Silbermann-Sorge Temperament"),
340 _(
"The Silbermann-Sorge temperament is a meantone temperament used for "
341 "Baroque era organs by Gottfried Silbermann.") };
343 case MusicalTuning::WERCKMEISTER_3:
344 return {
_(
"Werckmeister III"),
345 _(
"This tuning uses mostly pure (perfect) fifths, as in Pythagorean tuning, but each "
346 "of the fifths C-G, G-D, D-A and B-F# is made smaller, i.e. tempered by 1/4 comma. "
347 "Werckmeister designated this tuning as particularly suited for playing chromatic music.") };
348 case MusicalTuning::WERCKMEISTER_4:
349 return {
_(
"Werckmeister IV"),
350 _(
"In this tuning the fifths C-G, D-A, E-B, F#-C#, and Bb-F are tempered narrow by 1/3 comma, "
351 "and the fifths G#-D# and Eb-Bb are widened by 1/3 comma. The other fifths are pure. "
352 "Most of its intervals are close to sixth-comma meantone. "
353 "Werckmeister designed this tuning for playing mainly diatonic music.") };
354 case MusicalTuning::WERCKMEISTER_5:
355 return {
_(
"Werckmeister V"),
356 _(
"In this tuning the fifths D-A, A-E, F#-C#, C#-G#, and F-C are narrowed by 1/4 comma, "
357 "and the fifth G#-D# is widened by 1/4 comma. The other fifths are pure. "
358 "This temperament is closer to equal temperament than Werckmeister III or IV.") };
359 case MusicalTuning::WERCKMEISTER_6:
360 return {
_(
"Werckmeister VI"),
361 _(
"This tuning is also known as Septenarius tuning is based on a division of the monochord "
362 "length into 196 = 7 * 7 * 4 parts. "
363 "The resulting scale has rational frequency relationships, but in practice involves pure "
364 "and impure sounding fifths. "
365 "Werckmeister described the Septenarius as a \"temperament which has nothing at all to do "
366 "with the divisions of the comma, nevertheless in practice so correct that one can be really "
367 "satisfied with it\".") };
368 case MusicalTuning::KIRNBERGER_3:
369 return {
_(
"Kirnberger III"),
370 _(
"Kirnberger's method of compensating for and closing the circle of fifths is to split the \"wolf\" "
371 "interval known to those who have used meantone temperaments between four fifths instead, "
372 "allowing for four 1/4-comma wolves to take their place. "
373 "1/4-comma wolves are used extensively in meantone and are much easier to tune and to listen to. "
374 "Therefore, only one third remains pure (between C and E).") };
375 case MusicalTuning::YOUNG:
376 return {
_(
"Young Temperament"),
377 _(
"Thomas Young devised a form of musical tuning to make the harmony most perfect in those keys which "
378 "are the most frequently used (give better major thirds in those keys), but to not have any unplayable keys. "
379 "This is attempted by tuning upwards from C a sequence of six pure fourths, "
380 "as well as six equally imperfect fifths.") };
385static bool musical_tuning_info__ = EnumInfo::impl (musical_tuning_info);
388ServerImpl::musical_tuning_blurb (
MusicalTuning musicaltuning)
const
390 return EnumInfo::value_info (musicaltuning).blurb;
394ServerImpl::musical_tuning_label (
MusicalTuning musicaltuning)
const
396 return EnumInfo::value_info (musicaltuning).label;
402ServerImpl::user_note (
const String &text,
const String &channel, UserNote::Flags flags,
const String &rest)
404 UserNote unote { user_note_id++, flags, channel.empty() ?
"misc" : channel, text, rest };
407 this->emit_event (
"usernote",
"", vrec);
410 if (!unote.rest.empty())
411 s +=
" (" + unote.rest +
")";
423ServerImpl::telemem_allocate (
uint32 length)
const
425 return telemetry_arena.
allocate (length);
429ServerImpl::telemem_release (Block telememblock)
const
431 telemetry_arena.
release (telememblock);
435ServerImpl::telemem_start ()
const
441validate_telemetry_segments (
const TelemetrySegmentS &segments,
size_t *payloadlength)
444 const TelemetrySegment *last =
nullptr;
445 for (
const auto &seg : segments)
447 if (last && seg.offset < last->offset + last->length)
449 if (seg.offset < 0 || (seg.offset & 3) || seg.length <= 0 || (seg.length & 3) ||
450 size_t (seg.offset + seg.length) > telemetry_size)
452 *payloadlength += seg.length;
458ASE_CLASS_DECLS (TelemetryPlan);
461 int32 interval_ms_ = -1;
462 LoopID timerid_ = LoopID::INVALID;
464 TelemetrySegmentS segments_;
465 const char *telemem_ =
nullptr;
467 void send_telemetry();
468 void setup (
const char *start,
size_t payloadlength,
const TelemetrySegmentS &plan,
int32 interval_ms);
476 size_t payloadlength = 0;
477 if (!validate_telemetry_segments (segments, &payloadlength))
479 warning (
"%s: invalid segment list",
"Ase::ServerImpl::broadcast_telemetry");
485 warning (
"%s: cannot broadcast telemetry without jsonapi connection",
"Ase::ServerImpl::broadcast_telemetry");
493 tplan->send_blob_ = jsonapi_connection_sender();
495 tplan->setup ((
const char*) telemetry_arena.
location(), payloadlength, segments, interval_ms);
500TelemetryPlan::setup (
const char *start,
size_t payloadlength,
const TelemetrySegmentS &segments,
int32 interval_ms)
502 if (timerid_ == LoopID::INVALID || interval_ms_ != interval_ms)
504 if (timerid_ != LoopID::INVALID)
505 main_loop->cancel (timerid_);
507 auto send_telemetry = [tplan] () { tplan->send_telemetry();
return true; };
508 interval_ms_ = interval_ms;
509 timerid_ = interval_ms <= 0 || segments.empty() ? LoopID::INVALID : main_loop->add (send_telemetry,
std::chrono::milliseconds (interval_ms));
511 if (timerid_ != LoopID::INVALID)
514 segments_ = segments;
515 payload_.
resize (payloadlength);
526TelemetryPlan::send_telemetry ()
529 if (!telemem_ || segments_.empty() || payload_.
empty())
531 char *
data = &payload_[0];
533 for (
const auto &seg : segments_)
535 memcpy (data + datapos, telemem_ + seg.offset, seg.length);
536 datapos += seg.length;
539 (void) send_blob_ (payload_);
542TelemetryPlan::~TelemetryPlan()
544 if (timerid_ != LoopID::INVALID)
547 if (!main_loop->has_quit())
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
T shared_from_this(T... args)
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.