1 //-*-C++-*-
2 /*
3  * KMix -- KDE's full featured mini mixer
4  *
5  *
6  * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
7  * 1996-2000 Christian Esken <esken@kde.org>
8  * Sven Fischer <herpes@kawo2.rwth-aachen.de>
9  * 2002 - Helio Chissini de Castro <helio@conectiva.com.br>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this program; if not, write to the Free
23  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  */
25 
26 #ifndef RANDOMPREFIX_MIXER_H
27 #define RANDOMPREFIX_MIXER_H
28 
29 #include <QList>
30 #include <QObject>
31 #include <QString>
32 
33 #include "core/volume.h"
34 #include "backends/mixer_backend.h"
35 #include "core/MasterControl.h"
36 #include "mixset.h"
37 #include "core/mixdevice.h"
38 #include "dbus/dbusmixerwrapper.h"
39 #include "kmixcore_export.h"
40 
41 class Volume;
42 class KConfig;
43 
44 class KMIXCORE_EXPORT Mixer : public QObject
45 {
46       Q_OBJECT
47 
48 public:
49 	/**
50 	 * Status for Mixer operations.
51 	 *
52 	 * OK_UNCHANGED is a special variant of OK. It must be implemented by
53 	 * backends that use needsPolling() == true. See Mixer_OSS.cpp for an
54 	 * example. Rationale is that we need a proper change check: Otherwise
55 	 * the DBUS Session Bus is massively spammed. Also quite likely the Mixer
56 	 * GUI might get updated all the time.
57 	 *
58 	 */
59     enum MixerError { OK=0, ERR_PERM=1, ERR_WRITE, ERR_READ,
60         ERR_OPEN, OK_UNCHANGED };
61 
62     Mixer(const QString &ref_driverName, int device);
63     virtual ~Mixer();
64 
65     static int numDrivers();
getDriverName()66     QString getDriverName() const		{ return (_mixerBackend->getDriverName()); }
67 
68     shared_ptr<MixDevice> find(const QString &devPK) const;
69     static Mixer* findMixer(const QString &mixer_id);
70 
71     void volumeSave(KConfig *config) const;
72     void volumeLoad(const KConfig *config);
73 
74     /// How many mixer backend devices
size()75     unsigned int size() const			{ return (_mixerBackend->m_mixDevices.count()); }
76 
77     /// Returns a pointer to the mix device whose type matches the value
78     /// given by the parameter and the array MixerDevNames given in
79     /// mixer_oss.cpp (0 is Volume, 4 is PCM, etc.)
80     shared_ptr<MixDevice> getMixdeviceById( const QString& deviceID ) const;
81 
82     /// Open/grab the mixer for further interaction
83     bool openIfValid();
84 
85     /// Returns whether the card is open/operational
86     bool isOpen() const;
87 
88     /// Close/release the mixer
89     virtual void close();
90 
91     /// Reads balance
92     int balance() const;
93 
94     /// Returns a detailed state message after errors. Only for diagnostic purposes, no i18n.
95     QString& stateMessage() const;
96 
97     /**
98      * Returns the name of the card/chip/hardware, as given by the driver. The name is NOT instance specific,
99      * so if you install two identical soundcards, two of them will deliver the same mixerName().
100      * Use this method if you need an instance-UNspecific name, e.g. for finding an appropriate
101      * mixer layout for this card, or as a prefix for constructing instance specific ID's like in id().
102      */
103     virtual QString getBaseName() const;
104 
105     /// Wrapper to Mixer_Backend
106     QString translateKernelToWhatsthis(const QString &kernelName) const;
107 
108     /**
109       * Get a name suitable for a human user to read, possibly with quoted ampersand.
110       * The latter is required by some GUI elements like QRadioButton or when used as a
111       * tab label, as '&' introduces an accelerator there.
112       *
113       * @param ampersandQuoted @c true if '&' characters are to be quoted
114       * @return the readable device name
115       */
116     QString readableName(bool ampersandQuoted = false) const;
117 
118     // Returns the name of the driver, e.g. "OSS" or "ALSA0.9"
119     static QString driverName(int num);
120 
121     /**
122      * Returns an unique ID of the Mixer. It currently looks like "<soundcard_descr>::<hw_number>:<driver>"
123      */
id()124     const QString &id() const			{ return (_id); }
125 
getCardInstance()126     int getCardInstance() const      		{ return _mixerBackend->getCardInstance(); }
127 
128     /// Returns an Universal Device Identification of the Mixer. This is an ID that relates to the underlying operating system.
129     // For OSS and ALSA this is taken from Solid (actually HAL). For Solaris this is just the device name.
130     // Examples:
131     // ALSA: /org/freedesktop/Hal/devices/usb_device_d8c_1_noserial_if0_sound_card_0_2_alsa_control__1
132     // OSS: /org/freedesktop/Hal/devices/usb_device_d8c_1_noserial_if0_sound_card_0_2_oss_mixer__1
133     // Solaris: /dev/audio
udi()134     const QString &udi() const			{ return _mixerBackend->udi(); }
135 
136     // Returns a DBus path for this mixer
137     // Used also by MixDevice to bind to this path
138     const QString dbusPath();
139 
140     static QList<Mixer *> &mixers();
141 
142     /******************************************
143     The KMix GLOBAL master card. Please note that KMix and KMixPanelApplet can have a
144     different MasterCard's at the moment (but actually KMixPanelApplet does not read/save this yet).
145     At the moment it is only used for selecting the Mixer to use in KMix's DockIcon.
146     ******************************************/
147     static void setGlobalMaster(QString ref_card, QString ref_control, bool preferred);
148     static shared_ptr<MixDevice> getGlobalMasterMD(bool fallbackAllowed = true);
149     static Mixer* getGlobalMasterMixer();
150     static Mixer* getGlobalMasterMixerNoFalback();
151     static MasterControl& getGlobalMasterPreferred(bool fallbackAllowed = true);
152 
153     QString getRecommendedDeviceId() const;
154 
155     /******************************************
156     The recommended master of this Mixer.
157     ******************************************/
158     shared_ptr<MixDevice> getLocalMasterMD() const;
159     void setLocalMasterMD(const QString &devPK);
160 
161     /**
162      * An icon for the mixer's master channel
163      */
164     QString iconName() const;
165 
166     /// get the actual MixSet
getMixSet()167     MixSet &getMixSet() const			{ return (_mixerBackend->m_mixDevices); }
168 
169     /// DBUS oriented methods
170     virtual void increaseVolume( const QString& mixdeviceID );
171     virtual void decreaseVolume( const QString& mixdeviceID );
172 
173     /// Says if we are dynamic (e.g. widgets can come and go)
174     virtual void setDynamic(bool dynamic = true)	{ m_dynamic = dynamic; }
isDynamic()175     virtual bool isDynamic() const			{ return (m_dynamic); }
176 
177     static bool dynamicBackendsPresent();
178     static bool pulseaudioPresent();
179 
180     virtual bool moveStream(const QString &id, const QString &destId);
181     virtual QString currentStreamDevice(const QString &id) const;
182 
mediaPlay(QString id)183     virtual int mediaPlay(QString id)		{ return _mixerBackend->mediaPlay(id); }
mediaPrev(QString id)184     virtual int mediaPrev(QString id)		{ return _mixerBackend->mediaPrev(id); }
mediaNext(QString id)185     virtual int mediaNext(QString id)		{ return _mixerBackend->mediaNext(id); }
186 
187     void commitVolumeChange( shared_ptr<MixDevice> md );
188 
189 public slots:
190     void readSetFromHWforceUpdate() const;
191 
192     virtual void setBalance(int balance); // sets the m_balance (see there)
193 
194 signals:
195     void newBalance(Volume& );
196     void controlChanged(void); // TODO remove?
197 
198 protected:
199     static QList<Mixer *> s_mixers;
200 
201 private:
202     void setBalanceInternal(Volume& vol);
203     void recreateId();
204     void increaseOrDecreaseVolume( const QString& mixdeviceID, bool decrease );
205 
206     Mixer_Backend *_mixerBackend;
207     QString _id;
208     QString _masterDevicePK;
209     int m_balance; // from -100 (just left) to 100 (just right)
210     bool m_dynamic;
211 
212     static MasterControl _globalMasterCurrent;
213     static MasterControl _globalMasterPreferred;
214 };
215 
216 #endif
217