2 * KMix -- KDE's full featured mini mixer
4 * Copyright 2006-2007 Christian Esken <esken@kde.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "mixer_backend.h"
24 // for the "ERR_" declartions, #include mixer.h
27 Mixer_Backend::Mixer_Backend(Mixer
*mixer
, int device
) :
28 m_devnum (device
) , m_isOpen(false), m_recommendedMaster(0), _mixer(mixer
), _pollingTimer(0)
31 // In all cases create a QTimer. We will use it once as a singleShot(), even if something smart
32 // like ::select() is possible (as in ALSA).
33 _pollingTimer
= new QTimer(); // will be started on open() and stopped on close()
34 connect( _pollingTimer
, SIGNAL(timeout()), this, SLOT(readSetFromHW()));
37 Mixer_Backend::~Mixer_Backend()
40 qDeleteAll(m_mixDevices
);
45 bool Mixer_Backend::openIfValid() {
48 if ( ret
== 0 && m_mixDevices
.count() > 0) {
50 // A better ID is now calculated in mixertoolbox.cpp, and set via setID(),
51 // but we want a somehow usable fallback just in case.
53 if ( needsPolling() ) {
54 _pollingTimer
->start(50);
57 // The initial state must be read manually
58 QTimer::singleShot( 50, this, SLOT( readSetFromHW() ) );
67 bool Mixer_Backend::isOpen() {
72 * Queries the backend driver whether there are new changes in any of the controls.
73 * If you cannot find out for a backend, return "true" - this is also the default implementation.
74 * @return true, if there are changes. Otherwise false is returned.
76 bool Mixer_Backend::prepareUpdateFromHW() {
82 * After calling this, readSetFromHW() will do a complete update. This will
83 * trigger emitting the appropriate signals like controlChanged().
85 * This method is useful, if you need to get a "refresh signal" - used at:
86 * 1) Start of KMix - so that we can be sure an initial signal is emitted
87 * 2) When reconstructing any MixerWidget (e.g. DockIcon after applying preferences)
89 void Mixer_Backend::readSetFromHWforceUpdate() const {
90 _readSetFromHWforceUpdate
= true;
95 You can call this to retrieve the freshest information from the mixer HW.
96 This method is also called regulary by the mixer timer.
98 void Mixer_Backend::readSetFromHW()
100 bool updated
= prepareUpdateFromHW();
101 if ( (! updated
) && (! _readSetFromHWforceUpdate
) ) {
102 // Some drivers (ALSA) are smart. We don't need to run the following
103 // time-consuming update loop if there was no change
104 kDebug(67100) << "Mixer::readSetFromHW(): smart-update-tick";
107 _readSetFromHWforceUpdate
= false;
109 int mdCount
= m_mixDevices
.count();
110 for(int i
=0; i
<mdCount
; ++i
)
112 MixDevice
*md
= m_mixDevices
[i
];
113 readVolumeFromHW( md
->id(), md
);
116 * This could be reworked:
117 * Plan: Read everything (incuding enum's) in readVolumeFromHW().
118 * readVolumeFromHW() should then be renamed to readHW().
120 md
->setEnumId( enumIdHW(md
->id()) );
123 emit
controlChanged();
127 * Return the MixDevice, that would qualify best as MasterDevice. The default is to return the
128 * first device in the device list. Backends can override this (i.e. the ALSA Backend does so).
129 * The users preference is NOT returned by this method - see the Mixer class for that.
131 MixDevice
* Mixer_Backend::recommendedMaster() {
132 if ( m_recommendedMaster
!= 0 ) {
133 return m_recommendedMaster
; // Backend has set a recommended master. Thats fine.
134 } // recommendation from Backend
135 else if ( m_mixDevices
.count() > 0 ) {
136 return m_mixDevices
.at(0); // Backend has NOT set a recommended master. Evil backend => lets help out.
137 } //first device (if exists)
139 // This should never ever happen, as KMix doe NOT accept soundcards without controls
140 kError(67100) << "Mixer_Backend::recommendedMaster(): returning invalid master. This is a bug in KMix. Please file a bug report stating how you produced this." << endl
;
141 return (MixDevice
*)0;
146 * Sets the ID of the currently selected Enum entry.
147 * This is a dummy implementation - if the Mixer backend
148 * wants to support it, it must implement the driver specific
149 * code in its subclass (see Mixer_ALSA.cpp for an example).
151 void Mixer_Backend::setEnumIdHW(const QString
& , unsigned int) {
156 * Return the ID of the currently selected Enum entry.
157 * This is a dummy implementation - if the Mixer backend
158 * wants to support it, it must implement the driver specific
159 * code in its subclass (see Mixer_ALSA.cpp for an example).
161 unsigned int Mixer_Backend::enumIdHW(const QString
& ) {
165 void Mixer_Backend::errormsg(int mixer_error
)
168 l_s_errText
= errorText(mixer_error
);
169 kError() << l_s_errText
<< "\n";
172 int Mixer_Backend::id2num(const QString
& id
)
177 QString
Mixer_Backend::errorText(int mixer_error
)
182 case Mixer::ERR_PERM
:
183 l_s_errmsg
= i18n("kmix:You do not have permission to access the mixer device.\n" \
184 "Please check your operating systems manual to allow the access.");
186 case Mixer::ERR_WRITE
:
187 l_s_errmsg
= i18n("kmix: Could not write to mixer.");
189 case Mixer::ERR_READ
:
190 l_s_errmsg
= i18n("kmix: Could not read from mixer.");
192 case Mixer::ERR_OPEN
:
193 l_s_errmsg
= i18n("kmix: Mixer cannot be found.\n" \
194 "Please check that the soundcard is installed and that\n" \
195 "the soundcard driver is loaded.\n");
198 l_s_errmsg
= i18n("kmix: Unknown error. Please report how you produced this error.");
204 #include "mixer_backend.moc"