/BGMDriver/BGMDriver/BGM_NullDevice.h

https://github.com/kyleneideck/BackgroundMusic · C Header · 186 lines · 113 code · 33 blank · 40 comment · 0 complexity · f3428c2a403aa7893cfe6ddfb9e8d0fc MD5 · raw file

  1. // This file is part of Background Music.
  2. //
  3. // Background Music is free software: you can redistribute it and/or
  4. // modify it under the terms of the GNU General Public License as
  5. // published by the Free Software Foundation, either version 2 of the
  6. // License, or (at your option) any later version.
  7. //
  8. // Background Music is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with Background Music. If not, see <http://www.gnu.org/licenses/>.
  15. //
  16. // BGM_NullDevice.h
  17. // BGMDriver
  18. //
  19. // Copyright © 2017 Kyle Neideck
  20. //
  21. // A device with one output stream that ignores any audio played on that stream.
  22. //
  23. // If we change BGMDevice's controls list, to match the output device set in BGMApp, we need to
  24. // change the OS X default device so other programs (including the OS X audio UI) will update
  25. // themselves. We could just change to the real output device and change back, but that could have
  26. // side effects the user wouldn't expect. For example, an app the user had muted might be unmuted
  27. // for a short period.
  28. //
  29. // Instead, BGMApp temporarily enables this device and uses it to toggle the default device. This
  30. // device is disabled at all other times so it can be hidden from the user. (We can't just use
  31. // kAudioDevicePropertyIsHidden because hidden devices can't be default and the HAL doesn't seem to
  32. // let devices change kAudioDevicePropertyIsHidden after setting it initially.)
  33. //
  34. // It might be worth eventually having a virtual device for each real output device, but this is
  35. // simpler and seems to work well enough for now.
  36. //
  37. #ifndef BGMDriver__BGM_NullDevice
  38. #define BGMDriver__BGM_NullDevice
  39. // SuperClass Includes
  40. #include "BGM_AbstractDevice.h"
  41. // Local Includes
  42. #include "BGM_Types.h"
  43. #include "BGM_Stream.h"
  44. // PublicUtility Includes
  45. #include "CAMutex.h"
  46. // System Includes
  47. #include <pthread.h>
  48. #pragma clang assume_nonnull begin
  49. class BGM_NullDevice
  50. :
  51. public BGM_AbstractDevice
  52. {
  53. #pragma mark Construction/Destruction
  54. public:
  55. static BGM_NullDevice& GetInstance();
  56. private:
  57. static void StaticInitializer();
  58. protected:
  59. BGM_NullDevice();
  60. virtual ~BGM_NullDevice();
  61. public:
  62. virtual void Activate();
  63. virtual void Deactivate();
  64. private:
  65. void SendDeviceIsAlivePropertyNotifications();
  66. #pragma mark Property Operations
  67. public:
  68. bool HasProperty(AudioObjectID inObjectID,
  69. pid_t inClientPID,
  70. const AudioObjectPropertyAddress& inAddress) const;
  71. bool IsPropertySettable(AudioObjectID inObjectID,
  72. pid_t inClientPID,
  73. const AudioObjectPropertyAddress& inAddress) const;
  74. UInt32 GetPropertyDataSize(AudioObjectID inObjectID,
  75. pid_t inClientPID,
  76. const AudioObjectPropertyAddress& inAddress,
  77. UInt32 inQualifierDataSize,
  78. const void* __nullable inQualifierData) const;
  79. void GetPropertyData(AudioObjectID inObjectID,
  80. pid_t inClientPID,
  81. const AudioObjectPropertyAddress& inAddress,
  82. UInt32 inQualifierDataSize,
  83. const void* __nullable inQualifierData,
  84. UInt32 inDataSize,
  85. UInt32& outDataSize,
  86. void* outData) const;
  87. void SetPropertyData(AudioObjectID inObjectID,
  88. pid_t inClientPID,
  89. const AudioObjectPropertyAddress& inAddress,
  90. UInt32 inQualifierDataSize,
  91. const void* inQualifierData,
  92. UInt32 inDataSize,
  93. const void* inData);
  94. #pragma mark IO Operations
  95. public:
  96. void StartIO(UInt32 inClientID);
  97. void StopIO(UInt32 inClientID);
  98. void GetZeroTimeStamp(Float64& outSampleTime,
  99. UInt64& outHostTime,
  100. UInt64& outSeed);
  101. #pragma clang diagnostic push
  102. #pragma clang diagnostic ignored "-Wunused-parameter"
  103. void WillDoIOOperation(UInt32 inOperationID,
  104. bool& outWillDo,
  105. bool& outWillDoInPlace) const;
  106. void BeginIOOperation(UInt32 inOperationID,
  107. UInt32 inIOBufferFrameSize,
  108. const AudioServerPlugInIOCycleInfo& inIOCycleInfo,
  109. UInt32 inClientID)
  110. { /* No-op */ };
  111. void DoIOOperation(AudioObjectID inStreamObjectID,
  112. UInt32 inClientID,
  113. UInt32 inOperationID,
  114. UInt32 inIOBufferFrameSize,
  115. const AudioServerPlugInIOCycleInfo& inIOCycleInfo,
  116. void* ioMainBuffer,
  117. void* __nullable ioSecondaryBuffer);
  118. void EndIOOperation(UInt32 inOperationID,
  119. UInt32 inIOBufferFrameSize,
  120. const AudioServerPlugInIOCycleInfo& inIOCycleInfo,
  121. UInt32 inClientID)
  122. { /* No-op */ };
  123. #pragma mark Implementation
  124. public:
  125. CFStringRef CopyDeviceUID() const
  126. { return CFSTR(kBGMNullDeviceUID); };
  127. void AddClient(const AudioServerPlugInClientInfo* inClientInfo)
  128. { /* No-op */ };
  129. void RemoveClient(const AudioServerPlugInClientInfo* inClientInfo)
  130. { /* No-op */ };
  131. void PerformConfigChange(UInt64 inChangeAction,
  132. void* __nullable inChangeInfo)
  133. { /* No-op */ };
  134. void AbortConfigChange(UInt64 inChangeAction,
  135. void* __nullable inChangeInfo)
  136. { /* No-op */ };
  137. #pragma clang diagnostic pop
  138. private:
  139. static pthread_once_t sStaticInitializer;
  140. static BGM_NullDevice* sInstance;
  141. #define kNullDeviceName "Background Music Null Device"
  142. #define kNullDeviceManufacturerName \
  143. "Background Music contributors"
  144. CAMutex mStateMutex;
  145. CAMutex mIOMutex;
  146. BGM_Stream mStream;
  147. UInt32 mClientsDoingIO = 0;
  148. Float64 mHostTicksPerFrame = 0.0;
  149. UInt64 mNumberTimeStamps = 0;
  150. UInt64 mAnchorHostTime = 0;
  151. };
  152. #pragma clang assume_nonnull end
  153. #endif /* BGMDriver__BGM_NullDevice */