1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5 
6 #ifndef MUMBLE_MUMBLE_AUDIOOUTPUT_H_
7 #define MUMBLE_MUMBLE_AUDIOOUTPUT_H_
8 
9 #include <boost/shared_ptr.hpp>
10 #include <QtCore/QObject>
11 #include <QtCore/QThread>
12 
13 // AudioOutput depends on User being valid. This means it's important
14 // to removeBuffer from here BEFORE MainWindow gets any UserLeft
15 // messages. Any decendant user should feel free to remove unused
16 // AudioOutputUser objects; it's better to recreate them than
17 // having them use resources while unused.
18 
19 #ifndef SPEAKER_FRONT_LEFT
20 #define SPEAKER_FRONT_LEFT              0x1
21 #define SPEAKER_FRONT_RIGHT             0x2
22 #define SPEAKER_FRONT_CENTER            0x4
23 #define SPEAKER_LOW_FREQUENCY           0x8
24 #define SPEAKER_BACK_LEFT               0x10
25 #define SPEAKER_BACK_RIGHT              0x20
26 #define SPEAKER_FRONT_LEFT_OF_CENTER    0x40
27 #define SPEAKER_FRONT_RIGHT_OF_CENTER   0x80
28 #define SPEAKER_BACK_CENTER             0x100
29 #define SPEAKER_SIDE_LEFT               0x200
30 #define SPEAKER_SIDE_RIGHT              0x400
31 #define SPEAKER_TOP_CENTER              0x800
32 #define SPEAKER_TOP_FRONT_LEFT          0x1000
33 #define SPEAKER_TOP_FRONT_CENTER        0x2000
34 #define SPEAKER_TOP_FRONT_RIGHT         0x4000
35 #define SPEAKER_TOP_BACK_LEFT           0x8000
36 #define SPEAKER_TOP_BACK_CENTER         0x10000
37 #define SPEAKER_TOP_BACK_RIGHT          0x20000
38 #endif
39 
40 #include "Audio.h"
41 #include "Message.h"
42 
43 class AudioOutput;
44 class ClientUser;
45 class AudioOutputUser;
46 class AudioOutputSample;
47 
48 typedef boost::shared_ptr<AudioOutput> AudioOutputPtr;
49 
50 class AudioOutputRegistrar {
51 	private:
52 		Q_DISABLE_COPY(AudioOutputRegistrar)
53 	public:
54 		static QMap<QString, AudioOutputRegistrar *> *qmNew;
55 		static QString current;
56 		static AudioOutputPtr newFromChoice(QString choice = QString());
57 
58 		const QString name;
59 		int priority;
60 
61 		AudioOutputRegistrar(const QString &n, int priority = 0);
62 		virtual ~AudioOutputRegistrar();
63 		virtual AudioOutput *create() = 0;
64 		virtual const QList<audioDevice> getDeviceChoices() = 0;
65 		virtual void setDeviceChoice(const QVariant &, Settings &) = 0;
66 		virtual bool canMuteOthers() const;
67 		virtual bool usesOutputDelay() const;
68 		virtual bool canExclusive() const;
69 };
70 
71 class AudioOutput : public QThread {
72 	private:
73 		Q_OBJECT
74 		Q_DISABLE_COPY(AudioOutput)
75 	private:
76 		float *fSpeakers;
77 		float *fSpeakerVolume;
78 		bool *bSpeakerPositional;
79 	protected:
80 		enum { SampleShort, SampleFloat } eSampleFormat;
81 		volatile bool bRunning;
82 		unsigned int iFrameSize;
83 		volatile unsigned int iMixerFreq;
84 		unsigned int iChannels;
85 		unsigned int iSampleSize;
86 		QReadWriteLock qrwlOutputs;
87 		QMultiHash<const ClientUser *, AudioOutputUser *> qmOutputs;
88 
89 		virtual void removeBuffer(AudioOutputUser *);
90 		void initializeMixer(const unsigned int *chanmasks, bool forceheadphone = false);
91 		bool mix(void *output, unsigned int nsamp);
92 	public:
93 		void wipe();
94 
95                 /// Construct an AudioOutput.
96                 ///
97                 /// This constructor is only ever called by Audio::startOutput(), and is guaranteed
98                 /// to be called on the application's main thread.
99 		AudioOutput();
100 
101                 /// Destroy an AudioOutput.
102                 ///
103                 /// This destructor is only ever called by Audio::stopOutput() and Audio::stop(),
104                 /// and is guaranteed to be called on the application's main thread.
105 		~AudioOutput() Q_DECL_OVERRIDE;
106 
107 		void addFrameToBuffer(ClientUser *, const QByteArray &, unsigned int iSeq, MessageHandler::UDPMessageType type);
108 		void removeBuffer(const ClientUser *);
109 		AudioOutputSample *playSample(const QString &filename, bool loop = false);
110 		void run() Q_DECL_OVERRIDE = 0;
111 		virtual bool isAlive() const;
112 		const float *getSpeakerPos(unsigned int &nspeakers);
113 		static float calcGain(float dotproduct, float distance);
114 		unsigned int getMixerFreq() const;
115 };
116 
117 #endif
118