libASPL
Loading...
Searching...
No Matches
Device.hpp
Go to the documentation of this file.
1// Copyright (c) libASPL authors
2// Licensed under MIT
3
4//! @file aspl/Device.hpp
5//! @brief Audio device object.
6
7#pragma once
8
9#include <aspl/Client.hpp>
11#include <aspl/DoubleBuffer.hpp>
13#include <aspl/MuteControl.hpp>
14#include <aspl/Object.hpp>
15#include <aspl/Stream.hpp>
17
18#include <CoreAudio/AudioServerPlugIn.h>
19
20#include <array>
21#include <atomic>
22#include <memory>
23#include <mutex>
24#include <optional>
25#include <string>
26#include <unordered_map>
27#include <variant>
28#include <vector>
29
30namespace aspl {
31
32//! Audio device parameters.
34{
35 //! Human-readable name of the device.
36 //! Used by default implementation of Device::GetName().
37 std::string Name = "libASPL Device";
38
39 //! Human readable name of the maker of the plug-in.
40 //! Used by default implementation of Device::GetManufacturer().
41 std::string Manufacturer = "libASPL";
42
43 //! Persistent token that can identify the same audio device across boot sessions.
44 //! Used by default implementation of Device::GetDeviceUID().
45 std::string DeviceUID = "";
46
47 //! Persistent token that can identify audio devices of the same kind.
48 //! Used by default implementation of Device::GetModelUID().
49 std::string ModelUID = "libaspl";
50
51 //! Human readable serial number of the device.
52 //! Used by default implementation of Device::GetSerialNumber().
53 std::string SerialNumber = "";
54
55 //! Human readable firmware version of the device.
56 //! Used by default implementation of Device::GetFirmwareVersion().
57 std::string FirmwareVersion = "";
58
59 //! URL that points to the device icon, e.g. in plugin resource bundle.
60 //! Used by default implementation of Device::GetIconURL().
61 std::string IconURL = "";
62
63 //! Bundle ID for an application that provides a GUI for configuring the device.
64 //! Used by default implementation of Device::GetConfigurationApplicationBundleID().
66
67 //! Whether the device can be the default device for content.
68 //! Used by default implementation of Device::GetCanBeDefaultDevice().
69 bool CanBeDefault = true;
70
71 //! Whether the device can be the default device for system sounds.
72 //! Used by default implementation of Device::GetCanBeDefaultSystemDevice().
74
75 //! Device sample rate.
76 //! Used by default implementation of Device::GetNominalSampleRate().
77 UInt32 SampleRate = 44100;
78
79 //! Preferred number of channels.
80 //! Used by default implementations of Device::GetPreferredChannelCount().
81 UInt32 ChannelCount = 2;
82
83 //! The presentation latency of the device, number of frames.
84 //! Used by default implementation of Device::GetLatency().
85 UInt32 Latency = 0;
86
87 //! How close to now it is allowed to read and write, number of frames.
88 //! Used by default implementation of Device::GetSafetyOffset().
89 UInt32 SafetyOffset = 0;
90
91 //! How many frames to expect between successive timestamps returned
92 //! from Device::GetZeroTimeStamp()
93 //! Used by default implementation of Device::GetZeroTimeStampPeriod().
94 //! If zero, assigned to SampleRate value, which means one second.
96
97 //! Whether the device clock should be considered stable.
98 //! Used by default implementation of Device::GetClockIsStable().
99 bool ClockIsStable = true;
100
101 //! Clock algorithm.
102 //! Used by default implementation of Device::GetClockAlgorithm().
103 AudioDeviceClockAlgorithmSelector ClockAlgorithm =
104 kAudioDeviceClockAlgorithmSimpleIIR;
105
106 //! Clock domain.
107 //! Used by default implementation of Device::GetClockDomain().
108 UInt32 ClockDomain = 0;
109
110 //! Whether IORequestHandler will handle mixed output from all clients,
111 //! or handle individual clients and perform mixing by itself.
112 //!
113 //! - When true, Device will invoke IORequestHandler::OnProcessMixedOutput() and
114 //! IORequestHandler::WriteMixedOutput().
115 //! It will be provided with the result of mixing of all clients.
116 //!
117 //! - When false, Device will invoke IORequestHandler::OnProcessClientOutput()
118 //! and IORequestHandler::WriteClientOutput().
119 //! It will be repeatedly called with the output from each client.
120 //! IORequestHandler is responsible for mixing in this case.
121 bool EnableMixing = true;
122
123 //! If true, realtime calls are logged to tracer.
124 //! This is not suitable for production use because tracer is not realtime-safe
125 //! and because realtime operations are too frequent.
127};
128
129//! Audio device object.
130//!
131//! Audio device is something to which applications (clients) can connect and do I/O.
132//!
133//! **Streams and controls**
134//!
135//! After creating device, and before publishing it to HAL, you should populate it with
136//! streams (Stream class) and controls (VolumeControl, MuteControl).
137//!
138//! Each stream can be either input or output; control can be input, output, and global.
139//! Input streams allow client to read from device; output streams allow clients to
140//! write to device. Controls allow clients or user to adjust processing settings.
141//!
142//! When a client performs I/O, it always specifies the stream. Each stream may
143//! represent its own source or destination of samples. Each stream also may have its
144//! own format, latency, and other attributes.
145//!
146//! The meaning of controls is device-specific. If desired, you can attach controls
147//! to a stream, and stream will take them into account when applying per-stream
148//! processing. However you're free to treat streams and controls in any other way.
149//!
150//! **I/O operations**
151//!
152//! Unlike other objects, in addition to property dispatch operations, Device class has
153//! a bunch of I/O-related operations exported to HAL.
154//!
155//! Default Device implementation performs some typical housekeeping by itself (like
156//! maintaining maps of clients and streams) and then delegates the principal part (like
157//! actually reading or writing samples) to two other classes: ControlRequestHandler (for
158//! non-realtime, control operations) and IORequestHandler (for realtime I/O operations).
159//!
160//! Typically you'll need default implementation of Device and custom implementation of
161//! IORequestHandler and probably ControlRequestHandler. Though, if default Device
162//! implementation does not fit your needs, you can override how it handles control and
163//! I/O requests from HAL and drop IORequestHandler and ControlRequestHandler at all.
164//!
165//! When you override IORequestHandler or Device I/O operations, remember that HAL invokes
166//! them on realtime thread and they should be realtime-safe.
167class Device : public Object
168{
169public:
170 //! Construct device.
171 explicit Device(std::shared_ptr<const Context> context,
172 const DeviceParameters& params = {});
173
174 //! @name Getters and setters
175 //! @{
176
177 //! Get device name.
178 //! Human readable name of the device.
179 //! Can be localized.
180 //! By default returns DeviceParameters::Name.
181 //! @note
182 //! Backs @c kAudioObjectPropertyName property.
183 virtual std::string GetName() const;
184
185 //! Get device manufacturer.
186 //! Human readable name of the maker of the plug-in.
187 //! Can be localized.
188 //! By default returns DeviceParameters::Manufacturer.
189 //! @note
190 //! Backs @c kAudioObjectPropertyManufacturer property.
191 virtual std::string GetManufacturer() const;
192
193 //! Get device UID.
194 //! Persistent token that can identify the same audio device across boot sessions.
195 //! Two instances of the same device must have different values for this property.
196 //! By default returns DeviceParameters::DeviceUID if it's non-empty, or otherwise
197 //! generates random UID.
198 //! @note
199 //! Backs @c kAudioDevicePropertyDeviceUID property.
200 virtual std::string GetDeviceUID() const;
201
202 //! Get model UID.
203 //! Persistent token that can identify audio devices of the same kind.
204 //! Two instances of the same device must have the same value for this property.
205 //! By default returns DeviceParameters::ModelUID.
206 //! @note
207 //! Backs @c kAudioDevicePropertyModelUID property.
208 virtual std::string GetModelUID() const;
209
210 //! Get serial number.
211 //! Human readable serial number of the device.
212 //! This is pure informational value which doesn't have to be unique.
213 //! By default returns DeviceParameters::SerialNumber.
214 //! @note
215 //! Backs @c kAudioObjectPropertySerialNumber property.
216 virtual std::string GetSerialNumber() const;
217
218 //! Get firmware version.
219 //! Human readable firmware version of the device.
220 //! This is pure informational value which doesn't have to be unique.
221 //! By default returns DeviceParameters::FirmwareVersion.
222 //! @note
223 //! Backs @c kAudioObjectPropertyFirmwareVersion property.
224 virtual std::string GetFirmwareVersion() const;
225
226 //! Get device icon URL.
227 //! Returns URL that points to the device icon, e.g in plugin resource bundle.
228 //! By default returns DeviceParameters::IconURL.
229 //! @note
230 //! Backs @c kAudioDevicePropertyIcon property.
231 virtual std::string GetIconURL() const;
232
233 //! Get bundle ID of configuration application.
234 //! The returned app should provides a GUI for configuring the device.
235 //! By default returns DeviceParameters::ConfigurationApplicationBundleID.
236 //! @note
237 //! Backs @c kAudioDevicePropertyConfigurationApplication property.
238 virtual std::string GetConfigurationApplicationBundleID() const;
239
240 //! Get device transport type.
241 //! Represents how the device is attached to the system.
242 //! Common values are defined in <CoreAudio/AudioHardwareBase.h>.
243 //! Default is kAudioDeviceTransportTypeVirtual.
244 //! @note
245 //! Backs @c kAudioDevicePropertyTransportType property.
246 virtual UInt32 GetTransportType() const;
247
248 //! Get related devices.
249 //! By default returns a single-element list with own ID.
250 //! @remarks
251 //! The related devices property identifies device objects that are very closely
252 //! related. Generally, this is for relating devices that are packaged together
253 //! in the hardware such as when the input side and the output side of a piece
254 //! of hardware can be clocked separately and therefore need to be represented
255 //! as separate AudioDevice objects. In such case, both devices would report
256 //! that they are related to each other. Note that at minimum, a device is
257 //! related to itself, so this list will always be at least one item long.
258 //! @note
259 //! Backs @c kAudioDevicePropertyRelatedDevices property.
260 virtual std::vector<AudioObjectID> GetRelatedDeviceIDs() const;
261
262 //! Check whether the device clock should be considered stable.
263 //! By default returns DeviceParameters::ClockIsStable.
264 //! @remarks
265 //! The true value indicates that the device's clock runs at or very near the nominal
266 //! sample rate with only small variations.
267 //! @note
268 //! Backs @c kAudioDevicePropertyClockIsStable property.
269 virtual bool GetClockIsStable() const;
270
271 //! Get clock algorithm.
272 //! By default returns DeviceParameters::ClockAlgorithm.
273 //! @remarks
274 //! This property defines what filtering the HAL applies to the values returned
275 //! by GetZeroTimeStamp(). Possible values are defined in
276 //! CoreAudio/AudioServerPlugIn.h.
277 //! @note
278 //! Backs @c kAudioDevicePropertyClockAlgorithm property.
279 virtual AudioDeviceClockAlgorithmSelector GetClockAlgorithm() const;
280
281 //! Get clock domain.
282 //! By default returns DeviceParameters::ClockDomain.
283 //! @remarks
284 //! This property allows the device to declare what other devices it is
285 //! synchronized with in hardware. The way it works is that if two devices have
286 //! the same value for this property and the value is not zero, then the two
287 //! devices are synchronized in hardware. Note that a device that either can't
288 //! be synchronized with others or doesn't know should return 0 for this property.
289 //! @note
290 //! Backs @c kAudioDevicePropertyClockDomain property.
291 virtual UInt32 GetClockDomain() const;
292
293 //! Get presentation latency of the device.
294 //! Measured in number of frames.
295 //! By default returns the last value set by SetLatencyAsync().
296 //! Initial value is DeviceParameters::Latency.
297 //! @note
298 //! Backs @c kAudioDevicePropertyLatency property.
299 virtual UInt32 GetLatency() const;
300
301 //! Asynchronously set presentation latency.
302 //! Requests HAL to asynchronously invoke SetLatencyImpl().
303 OSStatus SetLatencyAsync(UInt32 latency);
304
305 //! How close to now it is allowed to read and write.
306 //! Measured in number of frames.
307 //! By default returns the last value set by SetSafetyOffset().
308 //! Initial value is DeviceParameters::SafetyOffset.
309 //! @note
310 //! Backs @c kAudioDevicePropertySafetyOffset property.
311 virtual UInt32 GetSafetyOffset() const;
312
313 //! Asynchronously set safety offset.
314 //! Requests HAL to asynchronously invoke SetSafetyOffsetImpl().
315 OSStatus SetSafetyOffsetAsync(UInt32 offset);
316
317 //! Difference between successive timestamps returned from GetZeroTimeStamp().
318 //! Measured in number of frames.
319 //! By default returns the last value set by SetZeroTimeStampPeriodAsync().
320 //! Initial value is DeviceParameters::ZeroTimeStampPeriod if it's non-zero,
321 //! or DeviceParameters::SampleRate otherwise.
322 //! @remarks
323 //! If GetZeroTimeStamp() returned a sample time of X, we expect that the next
324 //! valid returned timestamp will be X plus the value of this property.
325 //! @note
326 //! Backs @c kAudioDevicePropertyZeroTimeStampPeriod property.
327 virtual UInt32 GetZeroTimeStampPeriod() const;
328
329 //! Asynchronously set zero timestamp period.
330 //! Requests HAL to asynchronously invoke SetZeroTimeStampPeriodImpl().
331 OSStatus SetZeroTimeStampPeriodAsync(UInt32 period);
332
333 //! Get nominal sample rate.
334 //! By default returns the last value set by SetNominalSampleRateAsync().
335 //! Initial value is DeviceParameters::SampleRate.
336 //! Note that each device stream can define its own sample rate in its
337 //! physical and virtual formats.
338 //! @note
339 //! Backs @c kAudioDevicePropertyNominalSampleRate property.
340 virtual Float64 GetNominalSampleRate() const;
341
342 //! Asynchronously set nominal sample rate.
343 //! Requests HAL to asynchronously invoke SetNominalSampleRateImpl().
344 //! Fails if rate is not present in GetAvailableSampleRates(), which by default
345 //! returns only one rate, provided during initialization.
346 //! If you want to make your device supporting multiple rates, you typically
347 //! need to override both of these methods.
348 //! @note
349 //! Backs @c kAudioDevicePropertyNominalSampleRate property.
350 OSStatus SetNominalSampleRateAsync(Float64 rate);
351
352 //! Get list of supported nominal sample rates.
353 //! By default returns the list set by SetAvailableSampleRatesAsync().
354 //! If nothing was set, returns a single-element list with a range which min and max
355 //! are both set to the value returned by GetNominalSampleRate().
356 //! @remarks
357 //! Empty list means that any rate is allowed.
358 //! For discrete sampler rates, the range should have the minimum value equal
359 //! to the maximum value.
360 //! @note
361 //! Backs @c kAudioDevicePropertyAvailableNominalSampleRates property.
362 virtual std::vector<AudioValueRange> GetAvailableSampleRates() const;
363
364 //! Asynchronously set list of supported nominal sample rates.
365 //! See comments for GetAvailableSampleRates().
366 //! Requests HAL to asynchronously invoke SetAvailableSampleRatesImpl().
367 OSStatus SetAvailableSampleRatesAsync(std::vector<AudioValueRange> rates);
368
369 //! Return which two channels to use as left/right for stereo data by default.
370 //! By default returns the last value set by SetPreferredChannelsForStereoAsync().
371 //! Initial value is {1, 2}.
372 //! Channel numbers are 1-based.
373 //! @note
374 //! Backs @c kAudioDevicePropertyPreferredChannelsForStereo property.
375 virtual std::array<UInt32, 2> GetPreferredChannelsForStereo() const;
376
377 //! Asynchronously set channels for stereo.
378 //! Channel numbers are 1-based.
379 //! Requests HAL to asynchronously invoke SetPreferredChannelsForStereoImpl().
380 OSStatus SetPreferredChannelsForStereoAsync(std::array<UInt32, 2> channels);
381
382 //! Get preferred number of channels.
383 //!
384 //! GetPreferredChannelCount() and SetPreferredChannelCountAsync() are the most
385 //! simple way to configure channels. Use them if all you need is to get/set
386 //! number of channels.
387 //!
388 //! If you need more precise configuration, see GetPreferredChannels() and
389 //! GetPreferredChannelLayout(). If you don't, you can ignore them; their default
390 //! implementation will use GetPreferredChannelCount().
391 //!
392 //! Default implementation of this method automatically checks what channel parameters
393 //! did you set (SetPreferredChannelCountAsync(), SetPreferredChannelsAsync(),
394 //! SetPreferredChannelLayoutAsync()), and returns number of channels based on that.
395 //!
396 //! If nothing was set, it just returns DeviceParameters::ChannelCount.
397 //!
398 //! @note
399 //! Indirectly backs @c kAudioDevicePropertyPreferredChannelLayout property
400 //! via GetPreferredChannels() / GetPreferredChannelLayout().
401 virtual UInt32 GetPreferredChannelCount() const;
402
403 //! Asynchronously set preferred channel count.
404 //! See comments for GetPreferredChannelCount().
405 //! Requests HAL to asynchronously invoke SetPreferredChannelCountImpl().
406 //! @note
407 //! Indirectly backs @c kAudioDevicePropertyPreferredChannelLayout property
408 //! via GetPreferredChannels() / GetPreferredChannelLayout().
409 OSStatus SetPreferredChannelCountAsync(UInt32 channelCount);
410
411 //! Get preferred channels for device.
412 //!
413 //! GetPreferredChannels() and SetPreferredChannelsAsync() are a more precise way to
414 //! configure channels. Use them if all you want to specify parameters of individual
415 //! channels, defined in AudioChannelDescription struct.
416 //!
417 //! If all you need is just to change number of channels, see
418 //! GetPreferredChannelCount() instead. And if you need even more precise
419 //! configuration, see GetPreferredChannelLayout().
420 //!
421 //! Default implementation of this method automatically checks what channel parameters
422 //! did you set (SetPreferredChannelsAsync(), SetPreferredChannelLayoutAsync()), and
423 //! returns channel array based on that.
424 //!
425 //! If nothing was set, it constructs channels with default parameters based on the
426 //! number of channels returned by GetPreferredChannelCount().
427 //!
428 //! @note
429 //! Indirectly backs @c kAudioDevicePropertyPreferredChannelLayout property
430 //! via GetPreferredChannelLayout().
431 virtual std::vector<AudioChannelDescription> GetPreferredChannels() const;
432
433 //! Asynchronously set preferred channels array.
434 //! See comments for GetPreferredChannels().
435 //! Requests HAL to asynchronously invoke SetPreferredChannelsImpl().
436 //! @note
437 //! Indirectly backs @c kAudioDevicePropertyPreferredChannelLayout property
438 //! via GetPreferredChannelLayout().
439 OSStatus SetPreferredChannelsAsync(std::vector<AudioChannelDescription> channels);
440
441 //! Get preferred AudioChannelLayout to use for the device.
442 //!
443 //! This is the most precise way to configure channels, by providing custom
444 //! AudioChannelLayout. In most cases, it is enough to use GetPreferredChannelCount()
445 //! or GetPreferredChannels() instead.
446 //!
447 //! Default implementation of this method automatically checks if you have set channel
448 //! layout using SetPreferredChannelLayoutAsync(), and returns it.
449 //!
450 //! If nothing was set, it constructs default channel layout based on the channels
451 //! returned by GetPreferredChannels().
452 //!
453 //! @remarks
454 //! AudioChannelLayout has variable size, which depends on the number of
455 //! channels. Hence, this methods returns a byte array instead of
456 //! AudioChannelLayout struct. The returned array contains a properly
457 //! formatted AudioChannelLayout struct.
458 //!
459 //! @note
460 //! Backs @c kAudioDevicePropertyPreferredChannelLayout property.
461 virtual std::vector<UInt8> GetPreferredChannelLayout() const;
462
463 //! Asynchronously set preferred channel layout.
464 //! See comments for GetPreferredChannelLayout().
465 //! The provided buffer should contain properly formatted AudioChannelLayout struct.
466 //! Requests HAL to asynchronously invoke SetPreferredChannelLayoutImpl().
467 OSStatus SetPreferredChannelLayoutAsync(std::vector<UInt8> channelLayout);
468
469 //! Check whether the device is doing I/O.
470 //! By default, returns true if I/O was activated using StartIO().
471 //! @note
472 //! Backs @c kAudioDevicePropertyDeviceIsRunning property.
473 virtual bool GetIsRunning() const;
474
475 //! Check whether device identification is in progress.
476 //! A true value indicates that the device hardware is drawing attention to itself,
477 //! typically by flashing or lighting up its front panel display. This makes it easy
478 //! for a user to associate the physical hardware with its representation in an app.
479 //! By default always returns false.
480 //! @note
481 //! Backs @c kAudioObjectPropertyIdentify property.
482 virtual bool GetIsIdentifying() const;
483
484 //! Start or stop device identification.
485 //! Invokes SetIsIdentifyingImpl() and NotifyPropertyChanged().
486 //! @note
487 //! Backs @c kAudioObjectPropertyIdentify property.
488 OSStatus SetIsIdentifying(bool);
489
490 //! Check whether the device is alive.
491 //! By default returns the last value set by SetIsAlive().
492 //! Initial value is true.
493 //! @remarks
494 //! It is not uncommon for a device to be dead but still momentarily
495 //! available in the device list.
496 //! @note
497 //! Backs @c kAudioDevicePropertyDeviceIsAlive property.
498 virtual bool GetIsAlive() const;
499
500 //! Mark device as alive or dead.
501 //! Invokes SetIsAliveImpl() and NotifyPropertyChanged().
502 OSStatus SetIsAlive(bool isAlive);
503
504 //! Check whether the device is hidden from clients.
505 //! By default returns the last value set by SetIsHidden().
506 //! Initial value is false.
507 //! @note
508 //! Backs @c kAudioDevicePropertyIsHidden property.
509 virtual bool GetIsHidden() const;
510
511 //! Mark or unmark device as hidden.
512 //! Invokes SetIsHiddenImpl() and NotifyPropertyChanged().
513 OSStatus SetIsHidden(bool isHidden);
514
515 //! Check whether the device can be the default device for content.
516 //! By default, returns the last value set by SetCanBeDefaultDevice().
517 //! Initial value is DeviceParameters::CanBeDefault.
518 //! @remarks
519 //! Default device is configured via Sound Preferences. This is the device which
520 //! applications will use to play their content or capture sound.
521 //! Nearly all devices should allow for this.
522 //! @note
523 //! Backs @c kAudioDevicePropertyDeviceCanBeDefaultDevice property.
524 virtual bool GetCanBeDefaultDevice() const;
525
526 //! Set whether the device can be the default device for content.
527 //! Invokes SetCanBeDefaultDeviceImpl() and NotifyPropertyChanged().
528 OSStatus SetCanBeDefaultDevice(bool value);
529
530 //! Check whether the device can be the default device for system sounds.
531 //! By default, returns the last value set by SetCanBeDefaultSystemDevice().
532 //! Initial value is DeviceParameters::CanBeDefaultForSystemSounds.
533 //! @remarks
534 //! Default system device is configured via Sound Preferences. It is used by
535 //! applications to play interface sounds.
536 //! @note
537 //! Backs @c kAudioDevicePropertyDeviceCanBeDefaultSystemDevice property.
538 virtual bool GetCanBeDefaultSystemDevice() const;
539
540 //! Set whether the device can be the default device for system sounds.
541 //! Invokes SetCanBeDefaultSystemDeviceImpl() and NotifyPropertyChanged().
542 OSStatus SetCanBeDefaultSystemDevice(bool value);
543
544 //! Get device streams.
545 //! Returns the list of owned streams.
546 //! Scope defines whether to return input streams, output streams, or both.
547 //! Default implementation returns all owned objects of given scope and
548 //! kAudioStreamClassID class.
549 //! @note
550 //! Backs @c kAudioDevicePropertyStreams property.
551 virtual std::vector<AudioObjectID> GetStreamIDs(
552 AudioObjectPropertyScope scope = kAudioObjectPropertyScopeGlobal) const;
553
554 //! Get device controls.
555 //! Returns the list of owned controls.
556 //! Scope defines whether to return input controls, output controls, or both.
557 //! Default implementation returns all owned objects of given scope and
558 //! kAudioControlClassID class and its derivatives, including volume and
559 //! mute controls.
560 //! @note
561 //! Backs @c kAudioObjectPropertyControlList property.
562 virtual std::vector<AudioObjectID> GetControlIDs(
563 AudioObjectPropertyScope scope = kAudioObjectPropertyScopeGlobal) const;
564
565 //! @}
566
567 //! @name Streams
568 //! @{
569
570 //! Get number of streams for given direction.
571 UInt32 GetStreamCount(Direction dir) const;
572
573 //! Get stream with given direction and zero-based index.
574 //! Returns nullptr if there are less than idx+1 streams.
575 std::shared_ptr<Stream> GetStreamByIndex(Direction dir, UInt32 idx) const;
576
577 //! Get stream with given object ID.
578 //! Returns nullptr if there is no such stream.
579 std::shared_ptr<Stream> GetStreamByID(AudioObjectID streamID) const;
580
581 //! Add stream + volume control + mute control.
582 //! @remarks
583 //! Constructs a new Stream, VolumeControl, and MuteControl instances with default
584 //! parameters adjusted to the stream direction and index.
585 //! Attaches volume and mute controls to the stream, so that
586 //! Stream::ApplyProcessing(), called by IORequestHandler, will take volume and
587 //! mute into account.
588 //! Also adds constructed objects to the owned object list.
589 //! @returns
590 //! added stream.
591 //! @note
592 //! The addition is split into two parts: synchronous and asynchronous. Objects
593 //! are constructed and initialized synchronously, but are added to the owned
594 //! objects list and published to HAL asynchronously (when HAL allows it).
595 //! Hence, GetStreamCount() and GetStreamByIndex() are updated immediately,
596 //! but GetOwnedObjectIDs(), GetStreamIDs(), etc. are updated some time later.
597 std::shared_ptr<Stream> AddStreamWithControlsAsync(Direction dir);
598
599 //! Add stream + volume control + mute control.
600 //! Same as AddStreamWithControlsAsync(Direction), but allows to provide
601 //! custom parameters.
602 std::shared_ptr<Stream> AddStreamWithControlsAsync(const StreamParameters& params);
603
604 //! Add stream to device.
605 //! @remarks
606 //! Constructs a new Stream instance with default parameters,
607 //! adjusted to the stream direction and index.
608 //! Also adds stream to the owned object list.
609 //! @returns
610 //! added stream.
611 //! @note
612 //! The addition is split into two parts: synchronous and asynchronous. Stream
613 //! is constructed and initialized synchronously, but is added to the owned
614 //! objects list and published to HAL asynchronously (when HAL allows it).
615 //! Hence, GetStreamCount() and GetStreamByIndex() are updated immediately,
616 //! but GetOwnedObjectIDs(), GetStreamIDs(), etc. are updated some time later.
617 std::shared_ptr<Stream> AddStreamAsync(Direction dir);
618
619 //! Add stream to device.
620 //! Same as AddStreamAsync(Direction), but allows to provide custom parameters.
621 std::shared_ptr<Stream> AddStreamAsync(const StreamParameters& params);
622
623 //! Add stream to device.
624 //! Same as AddStreamAsync(Direction), but allows to construct stream manually.
625 void AddStreamAsync(std::shared_ptr<Stream> stream);
626
627 //! Remove stream from device.
628 //! @remarks
629 //! Removes stream from device and the owned object list.
630 //! @note
631 //! The removal is split into two parts: synchronous and asynchronous. Stream
632 //! is removed from the stream list synchronously, but is excluded from the
633 //! owned objects asynchronously (when HAL allows it). Hence, GetStreamCount()
634 //! and GetStreamByIndex() are updated immediately, but GetOwnedObjectIDs(),
635 //! GetStreamIDs(), etc. are updated some time later.
636 void RemoveStreamAsync(std::shared_ptr<Stream> stream);
637
638 //! @}
639
640 //! @name Volume controls
641 //! @{
642
643 //! Get number of volume controls for given scope.
644 UInt32 GetVolumeControlCount(AudioObjectPropertyScope scope) const;
645
646 //! Get volume control with given scope and zero-based index.
647 //! Returns nullptr if there are less than idx+1 volume controls.
648 std::shared_ptr<VolumeControl> GetVolumeControlByIndex(AudioObjectPropertyScope scope,
649 UInt32 idx) const;
650
651 //! Get volume control with given object ID.
652 //! Returns nullptr if there is no such control.
653 std::shared_ptr<VolumeControl> GetVolumeControlByID(AudioObjectID controlID) const;
654
655 //! Add volume control to device.
656 //! @remarks
657 //! Constructs a new VolumeControl instance with default parameters,
658 //! adjusted to the volume control scope and index.
659 //! Also adds volume control to the owned object list.
660 //! @returns
661 //! added control.
662 //! @note
663 //! The addition is split into two parts: synchronous and asynchronous. Control
664 //! is constructed and initialized synchronously, but is added to the owned
665 //! objects list and published to HAL asynchronously (when HAL allows it).
666 //! Hence, GetVolumeControlCount() and GetVolumeControlByIndex() are updated
667 //! immediately, but GetOwnedObjectIDs(), GetControlIDs(), etc. are updated later.
668 std::shared_ptr<VolumeControl> AddVolumeControlAsync(AudioObjectPropertyScope scope);
669
670 //! Add volume control to device.
671 //! Same as AddVolumeControlAsync(Direction), but allows to provide custom parameters.
672 std::shared_ptr<VolumeControl> AddVolumeControlAsync(
673 const VolumeControlParameters& params);
674
675 //! Add volume control to device.
676 //! Same as AddVolumeControlAsync(Direction), but allows to construct control
677 //! manually.
678 void AddVolumeControlAsync(std::shared_ptr<VolumeControl> control);
679
680 //! Remove volume control from device.
681 //! @remarks
682 //! Removes control from device and the owned object list.
683 //! @note
684 //! The removal is split into two parts: synchronous and asynchronous. Control
685 //! is removed from the control list synchronously, but is excluded from the
686 //! owned objects asynchronously (when HAL allows it). Hence, GetVolumeControlCount()
687 //! and GetVolumeControlByIndex() are updated immediately, but GetOwnedObjectIDs(),
688 //! GetControlIDs(), etc. are updated some time later.
689 void RemoveVolumeControlAsync(std::shared_ptr<VolumeControl> control);
690
691 //! @}
692
693 //! @name Mute controls
694 //! @{
695
696 //! Get number of mute controls for given scope.
697 UInt32 GetMuteControlCount(AudioObjectPropertyScope scope) const;
698
699 //! Get mute control with given scope and zero-based index.
700 //! Returns nullptr if there are less than idx+1 mute controls.
701 std::shared_ptr<MuteControl> GetMuteControlByIndex(AudioObjectPropertyScope scope,
702 UInt32 idx) const;
703
704 //! Get mute control with given object ID.
705 //! Returns nullptr if there is no such control.
706 std::shared_ptr<MuteControl> GetMuteControlByID(AudioObjectID controlID) const;
707
708 //! Add mute control to device.
709 //! @remarks
710 //! Constructs a new MuteControl instance with default parameters,
711 //! adjusted to the mute control scope and index.
712 //! Also adds mute control to the owned object list.
713 //! @returns
714 //! added control.
715 //! @note
716 //! The addition is split into two parts: synchronous and asynchronous. Control
717 //! is constructed and initialized synchronously, but is added to the owned
718 //! objects list and published to HAL asynchronously (when HAL allows it).
719 //! Hence, GetMuteControlCount() and GetMuteControlByIndex() are updated
720 //! immediately, but GetOwnedObjectIDs(), GetControlIDs(), etc. are updated later.
721 std::shared_ptr<MuteControl> AddMuteControlAsync(AudioObjectPropertyScope scope);
722
723 //! Add mute control to device.
724 //! Same as AddMuteControlAsync(Direction), but allows to provide custom parameters.
725 std::shared_ptr<MuteControl> AddMuteControlAsync(const MuteControlParameters& params);
726
727 //! Add mute control to device.
728 //! Same as AddMuteControlAsync(Direction), but allows to construct control manually.
729 void AddMuteControlAsync(std::shared_ptr<MuteControl> control);
730
731 //! Remove mute control from device.
732 //! @remarks
733 //! Removes control from device and the owned object list.
734 //! @note
735 //! The removal is split into two parts: synchronous and asynchronous. Control
736 //! is removed from the control list synchronously, but is excluded from the
737 //! owned objects asynchronously (when HAL allows it). Hence, GetMuteControlCount()
738 //! and GetMuteControlByIndex() are updated immediately, but GetOwnedObjectIDs(),
739 //! GetControlIDs(), etc. are updated some time later.
740 void RemoveMuteControlAsync(std::shared_ptr<MuteControl> control);
741
742 //! @}
743
744 //! @name Control operations
745 //! @{
746
747 //! Set handler for control requests.
748 //! This is optional. You may provide a custom handler if you want to do
749 //! custom processing or want to inject custom client implementation.
750 void SetControlHandler(std::shared_ptr<ControlRequestHandler> handler);
751
752 //! Set handler for control requests (raw pointer overload).
753 //! This overload uses raw pointer instead of shared_ptr, and the user
754 //! is responsible for keeping handler object alive until it's reset
755 //! or Device is destroyed.
757
758 //! Get pointer to configured control handler.
759 //! Never returns null, if there is no handler, a no-op handler is used.
760 //! For details about life-time, see SetControlHandler().
762
763 //! Called before new client start I/O with the device.
764 //! Updates client map and invokes OnAddClient().
765 virtual OSStatus AddClient(AudioObjectID objectID,
766 const AudioServerPlugInClientInfo* rawClientInfo);
767
768 //! Called after a client finishes I/O with the device.
769 //! Updates client map and invokes OnRemoveClient().
770 virtual OSStatus RemoveClient(AudioObjectID objectID,
771 const AudioServerPlugInClientInfo* rawClientInfo);
772
773 //! Get number of clients.
774 UInt32 GetClientCount() const;
775
776 //! Get all clients.
777 std::vector<std::shared_ptr<Client>> GetClients() const;
778
779 //! Find client by client ID.
780 std::shared_ptr<Client> GetClientByID(UInt32 clientID) const;
781
782 //! Tell the device to start I/O.
783 //! Invokes ControlRequestHandler::OnStartIO() and updates GetIsRunning().
784 //! GetIsRunning() will return true until at least one client is doing I/O.
785 //! @note
786 //! Calls StartIOImpl(), which you can override if needed.
787 //! You can also replace I/O handling entirely by overriding top-level methods:
788 //! StartIO(), StopIO(), GetZeroTimeStamp(), WillDoIOOperation(),
789 //! BeginIOOperation(), DoIOOperation(), EndIOOperation().
790 //! If you override top-level (non-Impl) methods, you likely need to override
791 //! all of them together and implement your own locking.
792 //! @note
793 //! Invoked by HAL on non-realtime thread.
794 virtual OSStatus StartIO(AudioObjectID objectID, UInt32 clientID);
795
796 //! Tell the device to stop I/O.
797 //! Invokes ControlRequestHandler::OnStopIO() and updates GetIsRunning().
798 //! GetIsRunning() will return true until at least one client is doing I/O.
799 //! @note
800 //! Calls StopIOImpl(), which you can override if needed.
801 //! You can also replace I/O handling entirely by overriding top-level methods:
802 //! StartIO(), StopIO(), GetZeroTimeStamp(), WillDoIOOperation(),
803 //! BeginIOOperation(), DoIOOperation(), EndIOOperation().
804 //! If you override top-level (non-Impl) methods, you likely need to override
805 //! all of them together and implement your own locking.
806 //! @note
807 //! Invoked by HAL on non-realtime thread.
808 virtual OSStatus StopIO(AudioObjectID objectID, UInt32 clientID);
809
810 //! @}
811
812 //! @name I/O operations
813 //! @{
814
815 //! Set handler for I/O requests.
816 //! Its methods will be invoked when an I/O operation is performed.
817 //! They are always invoked on realtime thread, serialized.
818 //! You need to provide your own implementation if you want your device
819 //! to actually do something useful. Default implementation is suitable for
820 //! a null / black hole device.
821 void SetIOHandler(std::shared_ptr<IORequestHandler> handler);
822
823 //! Set handler for I/O requests (raw pointer overload).
824 //! This overload uses raw pointer instead of shared_ptr, and the user
825 //! is responsible for keeping handler object alive until it's reset
826 //! or Device is destroyed.
828
829 //! Get pointer to configured I/O handler.
830 //! Never returns null, if there is no handler, a no-op handler is used.
831 //! For details about life-time, see SetIOHandler().
833
834 //! Get the current zero time stamp for the device.
835 //! In default implementation, the zero time stamp and host time are increased
836 //! every GetZeroTimeStampPeriod() frames.
837 //! @remarks
838 //! The HAL models the timing of a device as a series of time stamps that relate the
839 //! sample time to a host time. The zero time stamps are spaced such that the sample
840 //! times are the value of kAudioDevicePropertyZeroTimeStampPeriod apart. This is
841 //! often modeled using a ring buffer where the zero time stamp is updated when
842 //! wrapping around the ring buffer.
843 //! @note
844 //! Calls GetZeroTimeStampImpl(), which you can override if needed.
845 //! See also comments for StartIO() and StopIO().
846 //! @note
847 //! Invoked by HAL on realtime thread.
848 virtual OSStatus GetZeroTimeStamp(AudioObjectID objectID,
849 UInt32 clientID,
850 Float64* outSampleTime,
851 UInt64* outHostTime,
852 UInt64* outSeed);
853
854 //! Asks device whether it want to perform the given phase of the IO cycle.
855 //! In default implementation, makes decision based on whether the device has input
856 //! and output streams, and what is returned by DeviceParameters::EnableMixing.
857 //! @note
858 //! Calls WillDoIOOperationImpl(), which you can override if needed.
859 //! See also comments for StartIO() and StopIO().
860 //! @note
861 //! Invoked by HAL on realtime thread.
862 virtual OSStatus WillDoIOOperation(AudioObjectID objectID,
863 UInt32 clientID,
864 UInt32 operationID,
865 Boolean* outWillDo,
866 Boolean* outWillDoInPlace);
867
868 //! Called before performing I/O operation.
869 //! By default does nothing.
870 //! @note
871 //! Calls BeginIOOperationImpl(), which you can override if needed.
872 //! See also comments for StartIO() and StopIO().
873 //! @note
874 //! Invoked by HAL on realtime thread.
875 virtual OSStatus BeginIOOperation(AudioObjectID objectID,
876 UInt32 clientID,
877 UInt32 operationID,
878 UInt32 ioBufferFrameSize,
879 const AudioServerPlugInIOCycleInfo* ioCycleInfo);
880
881 //! Perform an IO operation for a particular stream.
882 //! In default implementation, invokes corresponding method of I/O handler based on
883 //! passed operation type, for example OnReadInput() or OnWriteMixedOutput().
884 //! @note
885 //! Calls DoIOOperationImpl(), which you can override if needed.
886 //! See also comments for StartIO() and StopIO().
887 //! @note
888 //! Invoked by HAL on realtime thread.
889 virtual OSStatus DoIOOperation(AudioObjectID objectID,
890 AudioObjectID streamID,
891 UInt32 clientID,
892 UInt32 operationID,
893 UInt32 ioBufferFrameSize,
894 const AudioServerPlugInIOCycleInfo* ioCycleInfo,
895 void* ioMainBuffer,
896 void* ioSecondaryBuffer);
897
898 //! Called after performing I/O operation.
899 //! By default does nothing.
900 //! @note
901 //! Calls EndIOOperationImpl(), which you can override if needed.
902 //! See also comments for StartIO() and StopIO().
903 //! @note
904 //! Invoked by HAL on realtime thread.
905 virtual OSStatus EndIOOperation(AudioObjectID objectID,
906 UInt32 clientID,
907 UInt32 operationID,
908 UInt32 ioBufferFrameSize,
909 const AudioServerPlugInIOCycleInfo* ioCycleInfo);
910
911 //! @}
912
913 //! @name Configuration
914 //! @{
915
916 //! Request HAL to perform configuration update.
917 //! @remarks
918 //! This method is needed when we want to change parameters that can't be just
919 //! changed on fly, e.g. set sample rate or add a stream. In this case, we
920 //! ask HAL to schedule configuration update, defined by passed function, and
921 //! some time later HAL invokes PerformConfigurationChange(), which runs the
922 //! function. HAL may also invoke AbortConfigurationChange() instead.
923 //! @note
924 //! There are three cases when this method decides that it's safe to invoke the
925 //! function immediately ("in-place") instead of enqueueing it:
926 //! - If Context::Host is null, the method assumes that the entire plugin is not
927 //! yet initialized and published to HAL, and thus HAL doesn't use Device.
928 //! - If Device::HasOwner() is false, the method assumes that the device itself
929 //! is not added to the plugin hierarchy yet, and thus HAL doesn't use Device.
930 //! - If the method is invoked from PerformConfigurationChange(), it assumes
931 //! that we're already at the point where it's safe to change configuration.
932 virtual void RequestConfigurationChange(std::function<void()> func = {});
933
934 //! Request device to change its owner.
935 //! @remarks
936 //! This method is called by Device owner (Plugin object) when device is added
937 //! or removed to the plugin (and so becomes published or unpublished from HAL).
938 //! This method implements thread-safe changing of the ownership and handles
939 //! possible races with RequestConfigurationChange().
940 //! It is needed because RequestConfigurationChange() mechanism is tightly
941 //! coupled with the ownership state and should be taken into account when
942 //! ownership changes.
943 //! @note
944 //! Normally @p owner is always a pointer to Plugin, and @p shouldHaveOwnership
945 //! is true when adding device and false when removing.
946 //! This method is expected to do all necessary housekeeping and invoke
947 //! owner->AddOwnedObject(this) or owner->RemoveOwnedObject(this).
948 virtual void RequestOwnershipChange(Object* owner, bool shouldHaveOwnership);
949
950 //! Called by the Host to allow the device to perform a configuration change
951 //! that had been previously requested via a call to the Host method,
952 //! RequestDeviceConfigurationChange().
953 //! @note
954 //! Invoked by HAL on non-realtime thread.
955 virtual OSStatus PerformConfigurationChange(AudioObjectID objectID,
956 UInt64 changeAction,
957 void* changeInfo);
958
959 //! Called by the Host to tell the device not to perform a configuration change
960 //! that had been requested via a call to the Host method,
961 //! RequestDeviceConfigurationChange().
962 //! @note
963 //! Invoked by HAL on non-realtime thread.
964 virtual OSStatus AbortConfigurationChange(AudioObjectID objectID,
965 UInt64 changeAction,
966 void* changeInfo);
967
968 //! @}
969
970 //! @name Property dispatch
971 //! @{
972
973 //! Get class ID.
974 AudioClassID GetClass() const override;
975
976 //! Get base class ID.
977 AudioClassID GetBaseClass() const override;
978
979 //! Check if this object is instance of given base class.
980 bool IsInstance(AudioClassID classID) const override;
981
982 //! Check whether given property is present.
983 Boolean HasProperty(AudioObjectID objectID,
984 pid_t clientPID,
985 const AudioObjectPropertyAddress* address) const override;
986
987 //! Check whether given property can be changed.
988 OSStatus IsPropertySettable(AudioObjectID objectID,
989 pid_t clientPID,
990 const AudioObjectPropertyAddress* address,
991 Boolean* outIsSettable) const override;
992
993 //! Get size of property value in bytes.
994 OSStatus GetPropertyDataSize(AudioObjectID objectID,
995 pid_t clientPID,
996 const AudioObjectPropertyAddress* address,
997 UInt32 qualifierDataSize,
998 const void* qualifierData,
999 UInt32* outDataSize) const override;
1000
1001 //! Get property value.
1002 OSStatus GetPropertyData(AudioObjectID objectID,
1003 pid_t clientPID,
1004 const AudioObjectPropertyAddress* address,
1005 UInt32 qualifierDataSize,
1006 const void* qualifierData,
1007 UInt32 inDataSize,
1008 UInt32* outDataSize,
1009 void* outData) const override;
1010
1011 //! Change property value.
1012 OSStatus SetPropertyData(AudioObjectID objectID,
1013 pid_t clientPID,
1014 const AudioObjectPropertyAddress* address,
1015 UInt32 qualifierDataSize,
1016 const void* qualifierData,
1017 UInt32 inDataSize,
1018 const void* inData) override;
1019
1020 //! @}
1021
1022protected:
1023 //! @name Setters implementation
1024 //! @{
1025
1026 //! Set presentation latency.
1027 //! Invoked by SetLatencyAsync() to actually change latency.
1028 //! Default implementation just changes the value returned by GetLatency().
1029 virtual OSStatus SetLatencyImpl(UInt32 latency);
1030
1031 //! Set safety offset.
1032 //! Invoked by SetSafetyOffsetAsync() to actually change offset.
1033 //! Default implementation just changes the value returned by
1034 //! GetSafetyOffset().
1035 virtual OSStatus SetSafetyOffsetImpl(UInt32 offset);
1036
1037 //! Set zero timestamp period.
1038 //! Invoked by SetZeroTimeStampPeriodAsync() to actually change period.
1039 //! Default implementation just changes the value returned by
1040 //! GetZeroTimeStampPeriod().
1041 virtual OSStatus SetZeroTimeStampPeriodImpl(UInt32 period);
1042
1043 //! Set nominal sample rate.
1044 //! Invoked by SetNominalSampleRateAsync() to actually change the rate.
1045 //! Default implementation just changes the value returned by GetNominalSampleRate().
1046 //! @note
1047 //! Backs @c kAudioDevicePropertyNominalSampleRate property.
1048 virtual OSStatus SetNominalSampleRateImpl(Float64 rate);
1049
1050 //! Set list of supported nominal sample rates.
1051 //! Invoked by SetAvailableSampleRatesAsync() to actually change the list.
1052 //! Default implementation just updates the list returned by
1053 //! GetAvailableSampleRates().
1054 virtual OSStatus SetAvailableSampleRatesImpl(std::vector<AudioValueRange> rates);
1055
1056 //! Set channels for stereo.
1057 //! Invoked by SetPreferredChannelsForStereoAsync() to actually change the value.
1058 //! Default implementation just changes the value returned
1059 //! GetPreferredChannelsForStereo().
1060 virtual OSStatus SetPreferredChannelsForStereoImpl(std::array<UInt32, 2> channels);
1061
1062 //! Set preferred channel count.
1063 //! Invoked by SetPreferredChannelCountAsync() to actually change the value.
1064 //! Default implementation changes the value returned by GetPreferredChannelCount().
1065 //! By default, it also affects values returned by GetPreferredChannels() and
1066 //! GetPreferredChannelLayout().
1067 virtual OSStatus SetPreferredChannelCountImpl(UInt32 channelCount);
1068
1069 //! Invoked by SetPreferredChannelsAsync() to actually change the value.
1070 //! Default implementation changes the value returned by GetPreferredChannels().
1071 //! By default, it also affects values returned by GetPreferredChannelCount() and
1072 //! GetPreferredChannelLayout().
1074 std::vector<AudioChannelDescription> channels);
1075
1076 //! Invoked by SetPreferredChannelLayoutAsync() to actually change the value.
1077 //! Default implementation changes the value returned by GetPreferredChannelLayout().
1078 //! By default, it also affects values returned by GetPreferredChannelCount() and
1079 //! GetPreferredChannels().
1080 virtual OSStatus SetPreferredChannelLayoutImpl(std::vector<UInt8> channelLayout);
1081
1082 //! Start or stop device identification.
1083 //! This can be requested by UI, but probably makes little sense to virtual devices.
1084 //! By default always fails.
1085 //! Invoked by SetIsIdentifying().
1086 //! @note
1087 //! Backs @c kAudioObjectPropertyIdentify property.
1088 virtual OSStatus SetIsIdentifyingImpl(bool isIdentifying);
1089
1090 //! Mark device as alive or dead.
1091 //! By default just changes the value returned by GetIsAlive().
1092 //! Invoked by SetIsAlive().
1093 virtual OSStatus SetIsAliveImpl(bool isAlive);
1094
1095 //! Mark or unmark device as hidden.
1096 //! By default just changes the value returned by GetIsHidden().
1097 //! Invoked by SetIsHidden().
1098 virtual OSStatus SetIsHiddenImpl(bool isHidden);
1099
1100 //! Set whether the device can be the default device for content.
1101 //! By default just changes the value returned by GetCanBeDefaultDevice().
1102 //! Invoked by SetCanBeDefaultDevice().
1103 virtual OSStatus SetCanBeDefaultDeviceImpl(bool value);
1104
1105 //! Set whether the device can be the default device for system sounds.
1106 //! By default just changes the value returned by GetCanBeDefaultSystemDevice().
1107 //! Invoked by SetCanBeDefaultSystemDevice().
1108 virtual OSStatus SetCanBeDefaultSystemDeviceImpl(bool value);
1109
1110 //! @}
1111
1112 //! @name I/O implementation
1113 //! @{
1114
1115 //! Prepare device to start I/O.
1116 //! Invoked by StartIO().
1117 //! @remarks
1118 //! StartIOImpl() is responsible for preparing to serve I/O requests.
1119 //! Default implementation invokes ControlRequestHandler::OnStartIO() and
1120 //! resets anchor timestamp and period counters, which are then used by
1121 //! GetZeroTimeStampImpl().
1122 //! @note
1123 //! startCount is incremented each time when StartIO() is called, and
1124 //! decremented when StopIO() is called. Zero startCount means that
1125 //! the device is switching from non-running to running state, and
1126 //! often only this case needs handling in StartIOImpl().
1127 //! @note
1128 //! StartIOImpl() gets startCount before it's incremented.
1129 //! @note
1130 //! For most uses cases, it is enough to provide ControlRequestHandler
1131 //! and there is no need to override this method.
1132 virtual OSStatus StartIOImpl(UInt32 clientID, UInt32 startCount);
1133
1134 //! Prepare device to finish I/O.
1135 //! Invoked by StopIO().
1136 //! @remarks
1137 //! StopIOImpl() is responsible for cleanup after serving I/O requests.
1138 //! Default implementation just invokes ControlRequestHandler::OnStopIO().
1139 //! @note
1140 //! startCount is incremented each time when StartIO() is called, and
1141 //! decremented when StopIO() is called. Zero startCount means that
1142 //! the device is switching from running to non-running state, and
1143 //! often only this case needs handling in StopIOImpl().
1144 //! @note
1145 //! StopIOImpl() gets startCount after it's decremented.
1146 //! @note
1147 //! For most uses cases, it is enough to provide ControlRequestHandler
1148 //! and there is no need to override this method.
1149 virtual OSStatus StopIOImpl(UInt32 clientID, UInt32 startCount);
1150
1151 //! Get the current zero timestamp for the device.
1152 //! Invoked by GetZeroTimeStamp().
1153 //! @remarks
1154 //! In default implementation, the zero time stamp and host time are increased
1155 //! every GetZeroTimeStampPeriod() frames. Default implementation also handles
1156 //! sample rate changes by checking GetNominalSampleRate().
1157 virtual OSStatus GetZeroTimeStampImpl(UInt32 clientID,
1158 Float64* outSampleTime,
1159 UInt64* outHostTime,
1160 UInt64* outSeed);
1161
1162 //! Asks device whether it want to perform the given phase of the IO cycle.
1163 //! Invoked by WillDoIOOperation().
1164 //! @remarks
1165 //! In default implementation, makes decision based on whether the device has input
1166 //! and output streams, and what is returned by DeviceParameters::EnableMixing.
1167 virtual OSStatus WillDoIOOperationImpl(UInt32 clientID,
1168 UInt32 operationID,
1169 Boolean* outWillDo,
1170 Boolean* outWillDoInPlace);
1171
1172 //! Called before performing I/O operation.
1173 //! Invoked by BeginIOOperation().
1174 //! @remarks
1175 //! Default implementation does nothing.
1176 virtual OSStatus BeginIOOperationImpl(UInt32 clientID,
1177 UInt32 operationID,
1178 UInt32 ioBufferFrameSize,
1179 const AudioServerPlugInIOCycleInfo* ioCycleInfo);
1180
1181 //! Perform an IO operation for a particular stream.
1182 //! Invoked by DoIOOperation().
1183 //! @remarks
1184 //! In default implementation, invokes corresponding method of I/O handler based on
1185 //! passed operation type, for example OnReadInput() or OnWriteMixedOutput().
1186 virtual OSStatus DoIOOperationImpl(AudioObjectID streamID,
1187 UInt32 clientID,
1188 UInt32 operationID,
1189 UInt32 ioBufferFrameSize,
1190 const AudioServerPlugInIOCycleInfo* ioCycleInfo,
1191 void* ioMainBuffer,
1192 void* ioSecondaryBuffer);
1193
1194 //! Called after performing I/O operation.
1195 //! Invoked by EndIOOperation().
1196 //! @remarks
1197 //! Default implementation does nothing.
1198 virtual OSStatus EndIOOperationImpl(UInt32 clientID,
1199 UInt32 operationID,
1200 UInt32 ioBufferFrameSize,
1201 const AudioServerPlugInIOCycleInfo* ioCycleInfo);
1202
1203 //! @}
1204
1205private:
1206 // value checkers for async setters
1207 OSStatus CheckNominalSampleRate(Float64 rate) const;
1208
1209 // these fields are immutable and can be accessed w/o lock
1210 const DeviceParameters params_;
1211 const std::string deviceUID_;
1212
1213 // these fields may be accessed by both control and I/O operations w/o lock
1214 std::atomic<UInt32> numInputStreams_ = 0;
1215 std::atomic<UInt32> numOutputStreams_ = 0;
1216
1217 std::atomic<bool> isAlive_ = true;
1218 std::atomic<bool> isHidden_ = false;
1219
1220 std::atomic<bool> canBeDefaultDevice_;
1221 std::atomic<bool> canBeDefaultSystemDevice_;
1222
1223 std::atomic<UInt32> latency_;
1224 std::atomic<UInt32> safetyOffset_;
1225 std::atomic<UInt32> zeroTimeStampPeriod_;
1226 std::atomic<Float64> nominalSampleRate_;
1227
1228 std::atomic<SInt32> startCount_ = 0;
1229
1230 // serializes writing to fields below
1231 mutable std::recursive_mutex writeMutex_;
1232
1234 DoubleBuffer<std::array<UInt32, 2>> preferredChannelsForStereo_;
1235 DoubleBuffer<std::optional<UInt32>> preferredChannelCount_;
1237 DoubleBuffer<std::optional<std::vector<UInt8>>> preferredChannelLayout_;
1238
1240 streams_;
1241
1243
1244 DoubleBuffer<std::unordered_map<AudioObjectPropertyScope,
1245 std::vector<std::shared_ptr<VolumeControl>>>>
1246 volumeControls_;
1247
1249 volumeControlByID_;
1250
1251 DoubleBuffer<std::unordered_map<AudioObjectPropertyScope,
1252 std::vector<std::shared_ptr<MuteControl>>>>
1253 muteControls_;
1254
1256 muteControlByID_;
1257
1259
1261 std::variant<std::shared_ptr<ControlRequestHandler>, ControlRequestHandler*>>
1262 controlHandler_;
1264 ioHandler_;
1265
1266 std::map<UInt64, std::function<void()>> pendingConfigurationRequests_;
1267 UInt64 lastConfigurationRequestID_ = 0;
1268 UInt64 insideConfigurationHandler_ = 0;
1269
1270 // serializes I/O operations and protects fields below
1271 mutable std::recursive_mutex ioMutex_;
1272
1273 // how much host clock ticks are per audio frame and what was the sample
1274 // rate when this value was calculated
1275 Float64 hostTicksPerFrame_ = 0;
1276 Float64 lastSampleRate_ = 0;
1277
1278 // time and period counter which are reset when I/O is (re-)started
1279 UInt64 anchorHostTime_ = 0;
1280 UInt64 periodCounter_ = 0;
1281
1282 // current zero timestamp, last values returned by GetZeroTimeStamp()
1283 Float64 currentPeriodTimestamp_ = 0;
1284 UInt64 currentPeriodHostTime_ = 0;
1285};
1286
1287} // namespace aspl
Client.
Handler for control requests to device.
Direction
I/O direction.
Definition Direction.hpp:15
Double buffer.
Handler for I/O requests to device.
Mute control object.
Basic audio object.
Audio stream object.
Volume control object.
Handler for control requests to device.
Audio device object.
Definition Device.hpp:168
OSStatus SetAvailableSampleRatesAsync(std::vector< AudioValueRange > rates)
Asynchronously set list of supported nominal sample rates. See comments for GetAvailableSampleRates()...
std::shared_ptr< VolumeControl > GetVolumeControlByID(AudioObjectID controlID) const
Get volume control with given object ID. Returns nullptr if there is no such control.
virtual OSStatus StartIO(AudioObjectID objectID, UInt32 clientID)
Tell the device to start I/O. Invokes ControlRequestHandler::OnStartIO() and updates GetIsRunning()....
virtual std::string GetFirmwareVersion() const
Get firmware version. Human readable firmware version of the device. This is pure informational value...
virtual OSStatus StopIOImpl(UInt32 clientID, UInt32 startCount)
Prepare device to finish I/O. Invoked by StopIO().
UInt32 GetClientCount() const
Get number of clients.
virtual bool GetClockIsStable() const
Check whether the device clock should be considered stable. By default returns DeviceParameters::Cloc...
AudioClassID GetClass() const override
Get class ID.
virtual std::string GetConfigurationApplicationBundleID() const
Get bundle ID of configuration application. The returned app should provides a GUI for configuring th...
Device(std::shared_ptr< const Context > context, const DeviceParameters &params={})
Construct device.
std::shared_ptr< Stream > GetStreamByIndex(Direction dir, UInt32 idx) const
Get stream with given direction and zero-based index. Returns nullptr if there are less than idx+1 st...
virtual void RequestOwnershipChange(Object *owner, bool shouldHaveOwnership)
Request device to change its owner.
virtual OSStatus SetPreferredChannelsImpl(std::vector< AudioChannelDescription > channels)
Invoked by SetPreferredChannelsAsync() to actually change the value. Default implementation changes t...
OSStatus SetIsIdentifying(bool)
Start or stop device identification. Invokes SetIsIdentifyingImpl() and NotifyPropertyChanged().
std::shared_ptr< MuteControl > AddMuteControlAsync(const MuteControlParameters &params)
Add mute control to device. Same as AddMuteControlAsync(Direction), but allows to provide custom para...
virtual OSStatus StartIOImpl(UInt32 clientID, UInt32 startCount)
Prepare device to start I/O. Invoked by StartIO().
OSStatus SetSafetyOffsetAsync(UInt32 offset)
Asynchronously set safety offset. Requests HAL to asynchronously invoke SetSafetyOffsetImpl().
virtual Float64 GetNominalSampleRate() const
Get nominal sample rate. By default returns the last value set by SetNominalSampleRateAsync()....
AudioClassID GetBaseClass() const override
Get base class ID.
OSStatus SetPreferredChannelLayoutAsync(std::vector< UInt8 > channelLayout)
Asynchronously set preferred channel layout. See comments for GetPreferredChannelLayout()....
std::shared_ptr< Stream > AddStreamWithControlsAsync(const StreamParameters &params)
Add stream + volume control + mute control. Same as AddStreamWithControlsAsync(Direction),...
virtual void RequestConfigurationChange(std::function< void()> func={})
Request HAL to perform configuration update.
virtual OSStatus StopIO(AudioObjectID objectID, UInt32 clientID)
Tell the device to stop I/O. Invokes ControlRequestHandler::OnStopIO() and updates GetIsRunning()....
virtual OSStatus SetPreferredChannelLayoutImpl(std::vector< UInt8 > channelLayout)
Invoked by SetPreferredChannelLayoutAsync() to actually change the value. Default implementation chan...
void AddVolumeControlAsync(std::shared_ptr< VolumeControl > control)
Add volume control to device. Same as AddVolumeControlAsync(Direction), but allows to construct contr...
OSStatus SetLatencyAsync(UInt32 latency)
Asynchronously set presentation latency. Requests HAL to asynchronously invoke SetLatencyImpl().
virtual OSStatus EndIOOperationImpl(UInt32 clientID, UInt32 operationID, UInt32 ioBufferFrameSize, const AudioServerPlugInIOCycleInfo *ioCycleInfo)
Called after performing I/O operation. Invoked by EndIOOperation().
void SetIOHandler(IORequestHandler *handler)
Set handler for I/O requests (raw pointer overload). This overload uses raw pointer instead of shared...
std::shared_ptr< Stream > AddStreamAsync(const StreamParameters &params)
Add stream to device. Same as AddStreamAsync(Direction), but allows to provide custom parameters.
virtual OSStatus SetIsIdentifyingImpl(bool isIdentifying)
Start or stop device identification. This can be requested by UI, but probably makes little sense to ...
OSStatus GetPropertyDataSize(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, UInt32 qualifierDataSize, const void *qualifierData, UInt32 *outDataSize) const override
Get size of property value in bytes.
virtual OSStatus GetZeroTimeStampImpl(UInt32 clientID, Float64 *outSampleTime, UInt64 *outHostTime, UInt64 *outSeed)
Get the current zero timestamp for the device. Invoked by GetZeroTimeStamp().
virtual OSStatus BeginIOOperation(AudioObjectID objectID, UInt32 clientID, UInt32 operationID, UInt32 ioBufferFrameSize, const AudioServerPlugInIOCycleInfo *ioCycleInfo)
Called before performing I/O operation. By default does nothing.
virtual OSStatus AddClient(AudioObjectID objectID, const AudioServerPlugInClientInfo *rawClientInfo)
Called before new client start I/O with the device. Updates client map and invokes OnAddClient().
virtual OSStatus SetPreferredChannelsForStereoImpl(std::array< UInt32, 2 > channels)
Set channels for stereo. Invoked by SetPreferredChannelsForStereoAsync() to actually change the value...
virtual std::vector< UInt8 > GetPreferredChannelLayout() const
Get preferred AudioChannelLayout to use for the device.
UInt32 GetStreamCount(Direction dir) const
Get number of streams for given direction.
Boolean HasProperty(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address) const override
Check whether given property is present.
virtual std::vector< AudioObjectID > GetStreamIDs(AudioObjectPropertyScope scope=kAudioObjectPropertyScopeGlobal) const
Get device streams. Returns the list of owned streams. Scope defines whether to return input streams,...
virtual UInt32 GetLatency() const
Get presentation latency of the device. Measured in number of frames. By default returns the last val...
virtual OSStatus SetPreferredChannelCountImpl(UInt32 channelCount)
Set preferred channel count. Invoked by SetPreferredChannelCountAsync() to actually change the value....
OSStatus SetPropertyData(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, UInt32 qualifierDataSize, const void *qualifierData, UInt32 inDataSize, const void *inData) override
Change property value.
virtual std::vector< AudioObjectID > GetControlIDs(AudioObjectPropertyScope scope=kAudioObjectPropertyScopeGlobal) const
Get device controls. Returns the list of owned controls. Scope defines whether to return input contro...
virtual OSStatus SetLatencyImpl(UInt32 latency)
Set presentation latency. Invoked by SetLatencyAsync() to actually change latency....
OSStatus SetCanBeDefaultSystemDevice(bool value)
Set whether the device can be the default device for system sounds. Invokes SetCanBeDefaultSystemDevi...
virtual std::string GetManufacturer() const
Get device manufacturer. Human readable name of the maker of the plug-in. Can be localized....
void RemoveMuteControlAsync(std::shared_ptr< MuteControl > control)
Remove mute control from device.
virtual std::string GetSerialNumber() const
Get serial number. Human readable serial number of the device. This is pure informational value which...
std::shared_ptr< VolumeControl > GetVolumeControlByIndex(AudioObjectPropertyScope scope, UInt32 idx) const
Get volume control with given scope and zero-based index. Returns nullptr if there are less than idx+...
virtual std::string GetName() const
Get device name. Human readable name of the device. Can be localized. By default returns DeviceParame...
std::shared_ptr< Stream > GetStreamByID(AudioObjectID streamID) const
Get stream with given object ID. Returns nullptr if there is no such stream.
UInt32 GetMuteControlCount(AudioObjectPropertyScope scope) const
Get number of mute controls for given scope.
virtual OSStatus SetSafetyOffsetImpl(UInt32 offset)
Set safety offset. Invoked by SetSafetyOffsetAsync() to actually change offset. Default implementatio...
virtual bool GetIsRunning() const
Check whether the device is doing I/O. By default, returns true if I/O was activated using StartIO().
virtual std::vector< AudioObjectID > GetRelatedDeviceIDs() const
Get related devices. By default returns a single-element list with own ID.
virtual std::string GetModelUID() const
Get model UID. Persistent token that can identify audio devices of the same kind. Two instances of th...
virtual UInt32 GetClockDomain() const
Get clock domain. By default returns DeviceParameters::ClockDomain.
OSStatus SetPreferredChannelsForStereoAsync(std::array< UInt32, 2 > channels)
Asynchronously set channels for stereo. Channel numbers are 1-based. Requests HAL to asynchronously i...
virtual std::string GetIconURL() const
Get device icon URL. Returns URL that points to the device icon, e.g in plugin resource bundle....
std::shared_ptr< Stream > AddStreamWithControlsAsync(Direction dir)
Add stream + volume control + mute control.
virtual bool GetCanBeDefaultSystemDevice() const
Check whether the device can be the default device for system sounds. By default, returns the last va...
virtual OSStatus SetAvailableSampleRatesImpl(std::vector< AudioValueRange > rates)
Set list of supported nominal sample rates. Invoked by SetAvailableSampleRatesAsync() to actually cha...
virtual bool GetIsAlive() const
Check whether the device is alive. By default returns the last value set by SetIsAlive()....
virtual std::vector< AudioValueRange > GetAvailableSampleRates() const
Get list of supported nominal sample rates. By default returns the list set by SetAvailableSampleRate...
std::shared_ptr< Client > GetClientByID(UInt32 clientID) const
Find client by client ID.
void RemoveStreamAsync(std::shared_ptr< Stream > stream)
Remove stream from device.
virtual OSStatus PerformConfigurationChange(AudioObjectID objectID, UInt64 changeAction, void *changeInfo)
Called by the Host to allow the device to perform a configuration change that had been previously req...
virtual UInt32 GetPreferredChannelCount() const
Get preferred number of channels.
void AddMuteControlAsync(std::shared_ptr< MuteControl > control)
Add mute control to device. Same as AddMuteControlAsync(Direction), but allows to construct control m...
virtual OSStatus SetNominalSampleRateImpl(Float64 rate)
Set nominal sample rate. Invoked by SetNominalSampleRateAsync() to actually change the rate....
virtual AudioDeviceClockAlgorithmSelector GetClockAlgorithm() const
Get clock algorithm. By default returns DeviceParameters::ClockAlgorithm.
OSStatus SetCanBeDefaultDevice(bool value)
Set whether the device can be the default device for content. Invokes SetCanBeDefaultDeviceImpl() and...
UInt32 GetVolumeControlCount(AudioObjectPropertyScope scope) const
Get number of volume controls for given scope.
virtual OSStatus SetIsHiddenImpl(bool isHidden)
Mark or unmark device as hidden. By default just changes the value returned by GetIsHidden()....
virtual std::array< UInt32, 2 > GetPreferredChannelsForStereo() const
Return which two channels to use as left/right for stereo data by default. By default returns the las...
void SetControlHandler(ControlRequestHandler *handler)
Set handler for control requests (raw pointer overload). This overload uses raw pointer instead of sh...
OSStatus SetPreferredChannelCountAsync(UInt32 channelCount)
Asynchronously set preferred channel count. See comments for GetPreferredChannelCount()....
virtual std::vector< AudioChannelDescription > GetPreferredChannels() const
Get preferred channels for device.
virtual OSStatus DoIOOperation(AudioObjectID objectID, AudioObjectID streamID, UInt32 clientID, UInt32 operationID, UInt32 ioBufferFrameSize, const AudioServerPlugInIOCycleInfo *ioCycleInfo, void *ioMainBuffer, void *ioSecondaryBuffer)
Perform an IO operation for a particular stream. In default implementation, invokes corresponding met...
void AddStreamAsync(std::shared_ptr< Stream > stream)
Add stream to device. Same as AddStreamAsync(Direction), but allows to construct stream manually.
virtual UInt32 GetTransportType() const
Get device transport type. Represents how the device is attached to the system. Common values are def...
virtual OSStatus SetIsAliveImpl(bool isAlive)
Mark device as alive or dead. By default just changes the value returned by GetIsAlive()....
OSStatus SetZeroTimeStampPeriodAsync(UInt32 period)
Asynchronously set zero timestamp period. Requests HAL to asynchronously invoke SetZeroTimeStampPerio...
virtual OSStatus EndIOOperation(AudioObjectID objectID, UInt32 clientID, UInt32 operationID, UInt32 ioBufferFrameSize, const AudioServerPlugInIOCycleInfo *ioCycleInfo)
Called after performing I/O operation. By default does nothing.
virtual bool GetCanBeDefaultDevice() const
Check whether the device can be the default device for content. By default, returns the last value se...
virtual OSStatus BeginIOOperationImpl(UInt32 clientID, UInt32 operationID, UInt32 ioBufferFrameSize, const AudioServerPlugInIOCycleInfo *ioCycleInfo)
Called before performing I/O operation. Invoked by BeginIOOperation().
void RemoveVolumeControlAsync(std::shared_ptr< VolumeControl > control)
Remove volume control from device.
virtual OSStatus GetZeroTimeStamp(AudioObjectID objectID, UInt32 clientID, Float64 *outSampleTime, UInt64 *outHostTime, UInt64 *outSeed)
Get the current zero time stamp for the device. In default implementation, the zero time stamp and ho...
virtual bool GetIsHidden() const
Check whether the device is hidden from clients. By default returns the last value set by SetIsHidden...
std::shared_ptr< VolumeControl > AddVolumeControlAsync(const VolumeControlParameters &params)
Add volume control to device. Same as AddVolumeControlAsync(Direction), but allows to provide custom ...
virtual OSStatus AbortConfigurationChange(AudioObjectID objectID, UInt64 changeAction, void *changeInfo)
Called by the Host to tell the device not to perform a configuration change that had been requested v...
virtual OSStatus DoIOOperationImpl(AudioObjectID streamID, UInt32 clientID, UInt32 operationID, UInt32 ioBufferFrameSize, const AudioServerPlugInIOCycleInfo *ioCycleInfo, void *ioMainBuffer, void *ioSecondaryBuffer)
Perform an IO operation for a particular stream. Invoked by DoIOOperation().
OSStatus SetIsHidden(bool isHidden)
Mark or unmark device as hidden. Invokes SetIsHiddenImpl() and NotifyPropertyChanged().
OSStatus GetPropertyData(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, UInt32 qualifierDataSize, const void *qualifierData, UInt32 inDataSize, UInt32 *outDataSize, void *outData) const override
Get property value.
OSStatus SetNominalSampleRateAsync(Float64 rate)
Asynchronously set nominal sample rate. Requests HAL to asynchronously invoke SetNominalSampleRateImp...
OSStatus IsPropertySettable(AudioObjectID objectID, pid_t clientPID, const AudioObjectPropertyAddress *address, Boolean *outIsSettable) const override
Check whether given property can be changed.
virtual OSStatus WillDoIOOperationImpl(UInt32 clientID, UInt32 operationID, Boolean *outWillDo, Boolean *outWillDoInPlace)
Asks device whether it want to perform the given phase of the IO cycle. Invoked by WillDoIOOperation(...
virtual OSStatus SetCanBeDefaultDeviceImpl(bool value)
Set whether the device can be the default device for content. By default just changes the value retur...
virtual OSStatus RemoveClient(AudioObjectID objectID, const AudioServerPlugInClientInfo *rawClientInfo)
Called after a client finishes I/O with the device. Updates client map and invokes OnRemoveClient().
virtual UInt32 GetZeroTimeStampPeriod() const
Difference between successive timestamps returned from GetZeroTimeStamp(). Measured in number of fram...
virtual OSStatus WillDoIOOperation(AudioObjectID objectID, UInt32 clientID, UInt32 operationID, Boolean *outWillDo, Boolean *outWillDoInPlace)
Asks device whether it want to perform the given phase of the IO cycle. In default implementation,...
virtual std::string GetDeviceUID() const
Get device UID. Persistent token that can identify the same audio device across boot sessions....
void SetIOHandler(std::shared_ptr< IORequestHandler > handler)
Set handler for I/O requests. Its methods will be invoked when an I/O operation is performed....
std::shared_ptr< MuteControl > GetMuteControlByID(AudioObjectID controlID) const
Get mute control with given object ID. Returns nullptr if there is no such control.
virtual OSStatus SetZeroTimeStampPeriodImpl(UInt32 period)
Set zero timestamp period. Invoked by SetZeroTimeStampPeriodAsync() to actually change period....
std::shared_ptr< MuteControl > GetMuteControlByIndex(AudioObjectPropertyScope scope, UInt32 idx) const
Get mute control with given scope and zero-based index. Returns nullptr if there are less than idx+1 ...
ControlRequestHandler * GetControlHandler() const
Get pointer to configured control handler. Never returns null, if there is no handler,...
bool IsInstance(AudioClassID classID) const override
Check if this object is instance of given base class.
void SetControlHandler(std::shared_ptr< ControlRequestHandler > handler)
Set handler for control requests. This is optional. You may provide a custom handler if you want to d...
std::shared_ptr< Stream > AddStreamAsync(Direction dir)
Add stream to device.
OSStatus SetIsAlive(bool isAlive)
Mark device as alive or dead. Invokes SetIsAliveImpl() and NotifyPropertyChanged().
OSStatus SetPreferredChannelsAsync(std::vector< AudioChannelDescription > channels)
Asynchronously set preferred channels array. See comments for GetPreferredChannels()....
std::shared_ptr< MuteControl > AddMuteControlAsync(AudioObjectPropertyScope scope)
Add mute control to device.
virtual OSStatus SetCanBeDefaultSystemDeviceImpl(bool value)
Set whether the device can be the default device for system sounds. By default just changes the value...
IORequestHandler * GetIOHandler() const
Get pointer to configured I/O handler. Never returns null, if there is no handler,...
std::shared_ptr< VolumeControl > AddVolumeControlAsync(AudioObjectPropertyScope scope)
Add volume control to device.
std::vector< std::shared_ptr< Client > > GetClients() const
Get all clients.
virtual UInt32 GetSafetyOffset() const
How close to now it is allowed to read and write. Measured in number of frames. By default returns th...
virtual bool GetIsIdentifying() const
Check whether device identification is in progress. A true value indicates that the device hardware i...
Doubly-buffered value with non-blocking read and blocking write.
Handler for I/O requests to device.
Base class for audio objects.
Definition Object.hpp:55
Audio device parameters.
Definition Device.hpp:34
std::string Manufacturer
Human readable name of the maker of the plug-in. Used by default implementation of Device::GetManufac...
Definition Device.hpp:41
std::string DeviceUID
Persistent token that can identify the same audio device across boot sessions. Used by default implem...
Definition Device.hpp:45
std::string Name
Human-readable name of the device. Used by default implementation of Device::GetName().
Definition Device.hpp:37
std::string SerialNumber
Human readable serial number of the device. Used by default implementation of Device::GetSerialNumber...
Definition Device.hpp:53
bool EnableMixing
Whether IORequestHandler will handle mixed output from all clients, or handle individual clients and ...
Definition Device.hpp:121
bool EnableRealtimeTracing
If true, realtime calls are logged to tracer. This is not suitable for production use because tracer ...
Definition Device.hpp:126
UInt32 SafetyOffset
How close to now it is allowed to read and write, number of frames. Used by default implementation of...
Definition Device.hpp:89
UInt32 ClockDomain
Clock domain. Used by default implementation of Device::GetClockDomain().
Definition Device.hpp:108
std::string FirmwareVersion
Human readable firmware version of the device. Used by default implementation of Device::GetFirmwareV...
Definition Device.hpp:57
std::string ConfigurationApplicationBundleID
Bundle ID for an application that provides a GUI for configuring the device. Used by default implemen...
Definition Device.hpp:65
AudioDeviceClockAlgorithmSelector ClockAlgorithm
Clock algorithm. Used by default implementation of Device::GetClockAlgorithm().
Definition Device.hpp:103
UInt32 SampleRate
Device sample rate. Used by default implementation of Device::GetNominalSampleRate().
Definition Device.hpp:77
UInt32 ZeroTimeStampPeriod
How many frames to expect between successive timestamps returned from Device::GetZeroTimeStamp() Used...
Definition Device.hpp:95
std::string ModelUID
Persistent token that can identify audio devices of the same kind. Used by default implementation of ...
Definition Device.hpp:49
bool CanBeDefaultForSystemSounds
Whether the device can be the default device for system sounds. Used by default implementation of Dev...
Definition Device.hpp:73
UInt32 ChannelCount
Preferred number of channels. Used by default implementations of Device::GetPreferredChannelCount().
Definition Device.hpp:81
bool ClockIsStable
Whether the device clock should be considered stable. Used by default implementation of Device::GetCl...
Definition Device.hpp:99
std::string IconURL
URL that points to the device icon, e.g. in plugin resource bundle. Used by default implementation of...
Definition Device.hpp:61
bool CanBeDefault
Whether the device can be the default device for content. Used by default implementation of Device::G...
Definition Device.hpp:69
UInt32 Latency
The presentation latency of the device, number of frames. Used by default implementation of Device::G...
Definition Device.hpp:85
Mute control parameters.
Audio stream parameters.
Definition Stream.hpp:29
Volume control parameters.