MythTV master
volumebase.cpp
Go to the documentation of this file.
1#include <cstdio>
2#include <cstdlib>
3
4#include <algorithm>
5
6#include <QString>
7#include <QMutex>
8#include <QMutexLocker>
9
10#include "libmythbase/mthread.h"
12
13#include "volumebase.h"
14
15
16namespace {
18{
19 VolumeWriteBackThread() : MThread("VolumeWriteBack") { }
20
21 public:
22 // Singleton
24 {
25 QMutexLocker lock(&s_mutex);
26 static auto *s_instance = new VolumeWriteBackThread;
27 return s_instance;
28 }
29
31 VolumeWriteBackThread & operator =(const VolumeWriteBackThread &) = delete;
32
33 void SetVolume(int value)
34 {
35 QMutexLocker lock(&m_mutex);
36
37 if (m_volume == value)
38 return;
39 m_volume = value;
40
41 switch (m_state)
42 {
43 case kRunning:
44 break;
45 case kFinished:
46 wait();
47 [[fallthrough]];
48 case kStopped:
49 m_state = kRunning;
50 start();
51 break;
52 }
53 }
54
55 protected:
56 void run(void) override // MThread
57 {
58 m_state = kRunning;
59 RunProlog();
60
61 static constexpr std::chrono::milliseconds holdoff { 500ms }; // min ms between Db writes
62 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");
63 controlLabel += "MixerVolume";
64
65 QMutexLocker lock(&m_mutex);
67 {
68 int volume = m_volume;
69 lock.unlock();
70
71 // Update the dbase with the new volume
72 gCoreContext->SaveSetting(controlLabel, volume);
73
74 // Ignore further volume changes for the holdoff period
75 setTerminationEnabled(true);
76 usleep(holdoff); // cppcheck-suppress usleepCalled
77 setTerminationEnabled(false);
78
79 lock.relock();
80 if (volume == m_volume)
81 break;
82 }
83
84 m_state = kFinished;
85 RunEpilog();
86 }
87
88 private:
89 static QMutex s_mutex;
90 QMutex mutable m_mutex;
91 enum : std::uint8_t { kStopped, kRunning, kFinished } m_state {kStopped};
92 int m_volume {-1};
93};
94
95QMutex VolumeWriteBackThread::s_mutex;
96} // namespace
97
98
100{
101 m_internalVol = gCoreContext->GetBoolSetting("MythControlsVolume", true);
103 (gCoreContext->GetSetting("MixerDevice", "default").toLower() == "software");
104}
105
106bool VolumeBase::SWVolume(void) const
107{
108 return m_swvol;
109}
110
112{
113 if (m_swvolSetting)
114 return;
115 m_swvol = set;
116}
117
119{
120 return m_volume;
121}
122
124{
125 m_volume = std::clamp(value, 0, 100);
126 UpdateVolume();
127
128 // Throttle Db writes
129 VolumeWriteBackThread::Instance()->SetVolume(m_volume);
130}
131
133{
134 SetCurrentVolume(m_volume + change);
135}
136
138{
139 m_currentMuteState = mstate;
140 UpdateVolume();
141 return m_currentMuteState;
142}
143
145{
146 bool is_muted = GetMuteState() == kMuteAll;
147 SetMuteState((is_muted) ? kMuteOff : kMuteAll);
148}
149
151{
152 return m_currentMuteState;
153}
154
156{
157 MuteState next = cur;
158
159 switch (cur)
160 {
161 case kMuteOff:
162 next = kMuteLeft;
163 break;
164 case kMuteLeft:
165 next = kMuteRight;
166 break;
167 case kMuteRight:
168 next = kMuteAll;
169 break;
170 case kMuteAll:
171 next = kMuteOff;
172 break;
173 }
174
175 return (next);
176}
177
179{
180 int new_volume = m_volume;
182 {
183 new_volume = 0;
184 }
185
186 if (m_swvol)
187 {
188 SetSWVolume(new_volume, false);
189 return;
190 }
191
192 for (int i = 0; i < m_channels; i++)
193 {
194 SetVolumeChannel(i, new_volume);
195 }
196
197 // Individual channel muting is handled in GetAudioData,
198 // this code demonstrates the old method.
199 // if (m_currentMuteState == kMuteLeft)
200 // {
201 // SetVolumeChannel(0, 0);
202 // }
203 // else if (m_currentMuteState == kMuteRight)
204 // {
205 // SetVolumeChannel(1, 0);
206 // }
207}
208
210{
211 // Read the volume from the audio driver and setup our internal state to match
212 if (m_swvol)
214 else
216}
217
218void VolumeBase::SetChannels(int new_channels)
219{
220 m_channels = new_channels;
221}
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
bool GetBoolSetting(const QString &key, bool defaultval=false)
static MuteState NextMuteState(MuteState)
Definition: volumebase.cpp:155
virtual MuteState GetMuteState(void) const
Definition: volumebase.cpp:150
int m_volume
Definition: volumebase.h:47
int m_channels
Definition: volumebase.h:51
bool m_swvolSetting
Definition: volumebase.h:50
bool SWVolume(void) const
Definition: volumebase.cpp:106
bool m_internalVol
Definition: volumebase.h:43
virtual void SetCurrentVolume(int value)
Definition: volumebase.cpp:123
virtual int GetSWVolume(void)=0
MuteState m_currentMuteState
Definition: volumebase.h:48
void UpdateVolume(void)
Definition: volumebase.cpp:178
virtual void SetSWVolume(int new_volume, bool save)=0
void SyncVolume(void)
Definition: volumebase.cpp:209
virtual uint GetCurrentVolume(void) const
Definition: volumebase.cpp:118
void SetChannels(int new_channels)
Definition: volumebase.cpp:218
virtual int GetVolumeChannel(int channel) const =0
virtual void SetVolumeChannel(int channel, int volume)=0
virtual MuteState SetMuteState(MuteState)
Definition: volumebase.cpp:137
virtual void ToggleMute(void)
Definition: volumebase.cpp:144
bool m_swvol
Definition: volumebase.h:49
virtual void AdjustCurrentVolume(int change)
Definition: volumebase.cpp:132
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: volumebase.cpp:56
VolumeWriteBackThread(const VolumeWriteBackThread &)=delete
unsigned int uint
Definition: freesurround.h:24
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:206
MuteState
Definition: volumebase.h:8
@ kMuteLeft
Definition: volumebase.h:10
@ kMuteOff
Definition: volumebase.h:9
@ kMuteRight
Definition: volumebase.h:11
@ kMuteAll
Definition: volumebase.h:12