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.