10#define DDEBUG(...)     Ase::debug ("driver", __VA_ARGS__) 
   15Driver::Driver (
const String &driver, 
const String &devid) :
 
   16  driver_ (driver), devid_ (devid)
 
   26  return devid_.
empty() ? driver_ : driver_ + 
"=" + devid_;
 
 
   31Driver::priority_string (
uint priority)
 
   34  if (priority & SURROUND)      b.
push_back (
"SURROUND");
 
   35  if (priority & HEADSET)       b.
push_back (
"HEADSET");
 
   36  if (priority & RECORDER)      b.
push_back (
"RECORDER");
 
   37  if (priority & MIDI_THRU)     b.
push_back (
"MIDI_THRU");
 
   38  if (priority & JACK)          b.
push_back (
"JACK");
 
   39  if (priority & ALSA_USB)      b.
push_back (
"ALSA_USB");
 
   40  if (priority & ALSA_KERN)     b.
push_back (
"ALSA_KERN");
 
   42  if (priority & PULSE)         b.
push_back (
"PULSE");
 
   43  if (priority & ALSA_USER)     b.
push_back (
"ALSA_USER");
 
   44  if (priority & PSEUDO)        b.
push_back (
"PSEUDO");
 
   45  if (priority & PAUTO)         b.
push_back (
"PAUTO");
 
   46  if (priority & PNULL)         b.
push_back (
"PNULL");
 
   47  if (priority & WCARD)         b.
push_back (
"WCARD");
 
   48  if (priority & WDEV)          b.
push_back (
"WDEV");
 
   49  if (priority & WSUB)          b.
push_back (
"WSUB");
 
 
   54using RegisteredLoaderFunc = 
Error (*) ();
 
   56  const char *
const what;
 
   57  const RegisteredLoaderFunc func;
 
 
   61static bool registered_loaders_executed = 
false;
 
   68  assert_return (registered_loaders_executed == 
false, 
nullptr);
 
   70  lv.push_back ({ staticwhat, loader });
 
   71  return ®istered_loaders_executed;
 
 
   79  registered_loaders_executed = 
true;
 
   80  for (
auto &loader : registered_loaders())
 
   82      Error error = loader.func ();
 
   83      if (error != Error::NONE)
 
   84        printerr (
"ASE: %s: loading failed: %s\n", loader.what, 
ase_error_blurb (error));
 
 
   89template<
typename DriverP>
 
   97  registered_driver_vector()
 
  100    return registered_driver_vector_;
 
  108    const String driverid = kvpair_key (devid);
 
  109    for (
const auto &driver : registered_driver_vector())
 
  110      if (driver.driver_id_ == driverid)
 
  112          create = driver.create_;
 
  115    Error error = Error::DEVICE_NOT_AVAILABLE;
 
  116    DriverP driver = create ? create (devid) : NULL;
 
  119        error = opener (driver, iodir);
 
  122        if (error == Error::NONE)
 
  125            assert_return (!(iodir & Driver::READONLY) || driver->readable(), 
nullptr);
 
  126            assert_return (!(iodir & Driver::WRITEONLY) || driver->writable(), 
nullptr);
 
  137  register_driver (
const String &driverid,
 
  141    auto &vec = registered_driver_vector();
 
  146  static Driver::EntryVec
 
  147  list_drivers (
const Driver::EntryVec &pseudos)
 
  149    Driver::EntryVec entries;
 
  151    auto &vec = registered_driver_vector();
 
  152    for (
const auto &rd : vec)
 
  154        Driver::EntryVec dentries;
 
  156        for (
auto &entry : dentries)
 
  157          entry.devid = entry.devid.empty() ? rd.driver_id_ : rd.driver_id_ + 
"=" + entry.devid;
 
  161        return a.priority < b.priority;
 
 
  168PcmDriver::PcmDriver (
const String &driver, 
const String &devid) :
 
  176  auto opener =  [&config] (
PcmDriverP d, IODir iodir) {
 
  177    return d->open (iodir, config);
 
  181      for (
const auto &entry : list_drivers())
 
  182        if (entry.priority < PSEUDO &&          
 
  183            !(entry.priority & 0x0000ffff))     
 
  187            if (!pcm_driver && required && desired != required) {
 
  198      if (!pcm_driver && required && desired != required)
 
 
  207PcmDriver::register_driver (
const String &driverid,
 
  215PcmDriver::list_drivers ()
 
  218  entry.devid = 
"auto";
 
  219  entry.device_name = 
_(
"Automatic driver selection");
 
  220  entry.device_info = 
_(
"Selects the first available PCM card or sound server");
 
  221  entry.readonly = 
false;
 
  222  entry.writeonly = 
false;
 
  223  entry.priority = Driver::PAUTO;
 
  224  Driver::EntryVec pseudos;
 
  225  pseudos.push_back (entry);
 
  226  return RegisteredDriver<PcmDriverP>::list_drivers (pseudos);
 
  230MidiDriver::MidiDriver (
const String &driver, 
const String &devid) :
 
  231  Driver (driver, devid)
 
  235MidiDriver::open (
const String &devid, IODir iodir, 
Error *ep)
 
  237  auto opener = [] (MidiDriverP d, IODir iodir) {
 
  238    return d->open (iodir);
 
  242      for (
const auto &entry : list_drivers())
 
  243        if (entry.priority < PSEUDO)    
 
  245            MidiDriverP midi_driver = RegisteredDriver<MidiDriverP>::open (entry.devid, iodir, ep, opener);
 
  253      MidiDriverP midi_driver = RegisteredDriver<MidiDriverP>::open (
devid, iodir, ep, opener);
 
  261MidiDriver::register_driver (
const String &driverid,
 
  265  return RegisteredDriver<MidiDriverP>::register_driver (driverid, create, list);
 
  269MidiDriver::list_drivers ()
 
  272  entry.devid = 
"auto";
 
  273  entry.device_name = 
_(
"Automatic MIDI driver selection");
 
  274  entry.device_info = 
_(
"Selects the first available MIDI device");
 
  275  entry.readonly = 
false;
 
  276  entry.writeonly = 
false;
 
  277  entry.priority = Driver::PAUTO;
 
  278  Driver::EntryVec pseudos;
 
  279  pseudos.push_back (entry);
 
  280  return RegisteredDriver<MidiDriverP>::list_drivers (pseudos);
 
  285  uint  n_channels_ = 0;
 
  287  uint  block_size_ = 0;
 
  288  int64 resumetime_ = 0;
 
  298  pcm_n_channels ()
 const override 
  303  pcm_mix_freq ()
 const override 
  308  pcm_block_length ()
 const override 
  313  pcm_latency (
uint *rlatency, 
uint *wlatency)
 const override 
  315    *rlatency = mix_freq_ / 10;
 
  316    *wlatency = mix_freq_ / 10;
 
  322    flags_ &= ~size_t (Flags::OPENED | Flags::READABLE | Flags::WRITABLE);
 
  329    const bool require_readable = iodir == READONLY || iodir == READWRITE;
 
  330    const bool require_writable = iodir == WRITEONLY || iodir == READWRITE;
 
  331    flags_ |= Flags::READABLE * require_readable;
 
  332    flags_ |= Flags::WRITABLE * require_writable;
 
  333    n_channels_ = config.n_channels;
 
  334    mix_freq_ = config.mix_freq;
 
  335    block_size_ = config.block_length;
 
  336    flags_ |= Flags::OPENED;
 
  337    DDEBUG (
"NULL-PCM: opening with freq=%f channels=%d: %s", mix_freq_, n_channels_, 
ase_error_blurb (Error::NONE));
 
  341  pcm_check_io (
int64 *timeout_usecs)
 override 
  344    if (resumetime_ > current_usecs)
 
  346        *timeout_usecs = resumetime_ - current_usecs;
 
  349    resumetime_ = current_usecs;
 
  353  pcm_write (
size_t n, 
const float *values)
 override 
  355    const int64 busy_usecs = n * 1000000 / (mix_freq_ * n_channels_);
 
  356    resumetime_ += busy_usecs;
 
  359  pcm_read (
size_t n, 
float *values)
 override 
  365  list_drivers (Driver::EntryVec &entries)
 
  369    entry.device_name = 
"Null PCM Driver";
 
  370    entry.device_info = 
_(
"Discard all PCM output and provide zeros as PCM input");
 
  371    entry.notice = 
"Warning: The Null driver has no playback timing support";
 
  372    entry.readonly = 
false;
 
  373    entry.writeonly = 
false;
 
  374    entry.priority = Driver::PNULL;
 
  375    entries.push_back (entry);
 
 
  379static const String null_pcm_driverid = PcmDriver::register_driver (
"null", NullPcmDriver::create, NullPcmDriver::list_drivers);
 
  395    flags_ &= ~size_t (Flags::OPENED | Flags::READABLE | Flags::WRITABLE);
 
  398  open (IODir iodir)
 override 
  402    const bool require_readable = iodir == READONLY || iodir == READWRITE;
 
  403    const bool require_writable = iodir == WRITEONLY || iodir == READWRITE;
 
  404    flags_ |= Flags::READABLE * require_readable;
 
  405    flags_ |= Flags::WRITABLE * require_writable;
 
  406    flags_ |= Flags::OPENED;
 
  411  has_events ()
 override 
  421  list_drivers (Driver::EntryVec &entries)
 
  425    entry.device_name = 
"Null MIDI Driver";
 
  426    entry.device_info = 
_(
"Discard all MIDI events");
 
  427    entry.readonly = 
false;
 
  428    entry.writeonly = 
false;
 
  429    entry.priority = Driver::PNULL;
 
  430    entries.push_back (entry);
 
 
  434static const String null_midi_driverid = MidiDriver::register_driver (
"null", NullMidiDriver::create, NullMidiDriver::list_drivers);
 
  442try_load_libasejack ()
 
  445  const std::string libasejack = string_format (
"%s/lib/jackdriver.so", anklang_runpath (RPath::INSTALLDIR));
 
  446  if (Path::check (libasejack, 
"fr"))
 
  448      void *dlhandle = 
dlopen (libasejack.
c_str(), RTLD_LOCAL | RTLD_NOW); 
 
  450      DDEBUG (
"%s: dlopen: %s", libasejack, dlhandle ? 
"OK" : err ? err : 
"unknown dlerror");
 
T back_inserter(T... args)
 
Base class for a PCM and MIDI devices.
 
String devid() const
Return a string which uniquely identifies this driver and device.
 
Base class for a MIDI devices.
 
A stream of writable MidiEvent structures.
 
Base class for a PCM devices.
 
#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.
 
T make_move_iterator(T... args)
 
The Anklang C++ API namespace.
 
void floatfill(float *dst, float f, size_t n)
Fill n values of dst with f.
 
String string_join(const String &junctor, const StringS &strvec)
 
int64_t int64
A 64-bit unsigned integer, use PRI*64 in format strings.
 
Error
Enum representing Error states.
 
const char * ase_error_blurb(Error error)
Describe Error condition.
 
bool * register_driver_loader(const char *staticwhat, Error(*loader)())
Register loader callbacks at static constructor time.
 
std::string String
Convenience alias for std::string.
 
uint32_t uint
Provide 'uint' as convenience type.
 
void load_registered_drivers()
Load all registered drivers.
 
uint64 timestamp_realtime()
Return the current time as uint64 in µseconds.
 
Driver information for PCM and MIDI handling.
 
PCM device configuration.